前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++模板坑,一起来issue

C++模板坑,一起来issue

作者头像
公众号guangcity
发布2020-04-24 17:14:24
6110
发布2020-04-24 17:14:24
举报
文章被收录于专栏:光城(guangcity)

C++模板坑,一起来issue

C++开发中通常将类定义放在C ++头文件(.h)中,并将实现放在C ++源文件(.cpp)中。然后,将源文件作为项目的一部分,这意味着将其单独编译。但是,当我们对模板类实施此过程时,将出现一些编译和链接问题。

本文阐述了三种可能的解决方案,帮助大家可以在实现该模板的源文件中创建一个模板类的对象,解决上述问题。

问题复现

头文件声明:

代码语言:javascript
复制
// temp.h
#ifndef _TEMP_H_
#define _TEMP_H_
#include <iostream>
#include <vector>
template <typename T>
using Vec = std::vector<T>;
#define PRINTFMT(x) std::cout << x << " ";

template <typename T>
void TestTemp(const Vec<T> &v, T target);
#endif

头文件实现:

代码语言:javascript
复制
#include "temp.h"


template <typename T>
void TestTemp(const Vec<T> &v, T target)
{
    [=]() {
        for (auto elem : v)
            if (elem == target)
                PRINTFMT(elem);
    }();
}

报错:

代码语言:javascript
复制
undefined reference to....

问题描述:当在.h中声明了模板,.cpp中定义了模板,当main函数去进行模板实例化的时候,在声明处找不到对应的T类型,自然就出问题了。

1.第一种:同一文件

声明及定义都在.h文件中。

代码语言:javascript
复制
// temp.h
#ifndef _TEMP_H_
#define _TEMP_H_
#include <iostream>
#include <vector>
template <typename T>
using Vec = std::vector<T>;
#define PRINTFMT(x) std::cout << x << " ";

template <typename T>
void TestTemp(const Vec<T> &v, T target)
{
    [=]() {
        for (auto elem : v)
            if (elem == target)
                PRINTFMT(elem);
    }();
}
#endif

2.第二种:分离开+引入头文件

采用头文件声明,cpp定义,要想起作用,得在使用处引入两者并且定义处得用特化版本。

例如:

头文件实现:

代码语言:javascript
复制
// Temp.cpp
#include "temp.h"

void TestTemp(const Vec<int> &v, int target)
{
    [=]() {
        for (auto elem : v)
            if (elem == target)
                PRINTFMT(elem);
    }();
}

template <typename T>
void TestTemp(const Vec<T> &v, T target)
{
    [=]() {
        for (auto elem : v)
            if (elem == target)
                PRINTFMT(elem);
    }();
}

实现:

代码语言:javascript
复制
#include "temp.h"
#include "temp.cpp"

int main() {
    std::vector<int> v{1,2,3};
    int target = 2;
    TestTemp<int>(v,target);

    return 0;
}

3.在末尾引入cpp

只需要在.h头文件末尾引入cpp即可。

头文件只需要声明:

代码语言:javascript
复制
// temp.h
#ifndef _TEMP_H_
#define _TEMP_H_
#include <iostream>
#include <vector>
template <typename T>
using Vec = std::vector<T>;
#define PRINTFMT(x) std::cout << x << " ";

template <typename T>
void TestTemp(const Vec<T> &v, T target);
#include "temp.cpp"
#endif

头文件定义即可:

代码语言:javascript
复制
// Temp.cpp
#include "temp.h"

template <typename T>
void TestTemp(const Vec<T> &v, T target)
{
    [=]() {
        for (auto elem : v)
            if (elem == target)
                PRINTFMT(elem);
    }();
}

调用处正常调用:

代码语言:javascript
复制
#include "temp.h"

int main() {
    std::vector<int> v{1,2,3};
    int target = 2;
    TestTemp<int>(v,target);

    return 0;
}

在一些开源项目中,这种方式比较常见,只不过这里的.cpp得改为.hpp。其余不变!

4.总结

本节针对日常代码中的难点进行了梳理,提出了几种解决方案。可以简单的把模板理解为一种特殊的宏,模板类不要当作类,在被实例化的时候一定得找到定义,不然只看到声明,就GG了。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-04-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 光城 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题复现
  • 1.第一种:同一文件
  • 2.第二种:分离开+引入头文件
  • 3.在末尾引入cpp
  • 4.总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档