当前位置:  开发笔记 > 编程语言 > 正文

在.CPP文件中存储C++模板函数定义

如何解决《在.CPP文件中存储C++模板函数定义》经验,为你挑选了6个好方法。

我有一些模板代码,我宁愿存储在CPP文件中而不是标题中的内联.我知道只要您知道将使用哪些模板类型,就可以完成此操作.例如:

.h文件

class foo
{
public:
    template 
    void do(const T& t);
};

.cpp文件

template 
void foo::do(const T& t)
{
    // Do something with t
}

template void foo::do(const int&);
template void foo::do(const std::string&);

注意最后两行--foo :: do模板函数仅用于int和std :: strings,因此这些定义意味着应用程序将链接.

我的问题是 - 这是一个讨厌的黑客还是会与其他编译器/链接器一起使用?我目前只在VS2008上使用此代码,但是想要移植到其他环境.



1> Aaron N. Tub..:

您描述的问题可以通过在标题中定义模板或通过您在上面描述的方法来解决.

我建议从C++ FAQ Lite中阅读以下几点:

为什么我不能将模板类的定义与其声明分开并将其放在.cpp文件中?

如何使用模板函数避免链接器错误?

C++关键字导出如何帮助解决模板链接器错误?

他们详细介绍了这些(和其他)模板问题.


你能在答案中发布相关部分吗?为什么在SO上允许这样的引用.我不知道在这个链接中要查找什么,因为它已经发生了很大变化.
为了补充答案,引用的链接肯定地回答了问题,即可以执行Rob建议并使代码可移植.

2> 小智..:

对于本页面上的其他人,想知道显式模板特化(或者至少在VS2008中)的正确语法是什么(就像我一样),它的以下内容......

在你的.h文件中......

template
class foo
{
public:
    void bar(const T &t);
};

并在您的.cpp文件中

template 
void foo::bar(const T &t)
{ }

// Explicit template instantiation
template class foo;


你的意思是"明确的CLASS模板专业".在那种情况下,它将覆盖模板类具有的每个函数吗?

3> Konrad Rudol..:

此代码格式正确.您只需要注意模板的定义在实例化时是可见的.引用标准,§14.7.2.4:

非导出函数模板,非导出成员函数模板或类模板的非导出成员函数或静态数据成员的定义应存在于显式实例化的每个转换单元中.


*非出口*是什么意思?

4> moonshadow..:

这应该适用于支持模板的所有地方.显式模板实例化是C++标准的一部分.



5> Cameron Tack..:

你的例子是正确的,但不是很便携.还可以使用稍微清晰的语法(如@ namespace-sid所指出的).

假设模板化类是要共享的某个库的一部分.是否应编译其他版本的模板化类?图书馆维护者是否应该预测该课程的所有可能的模板用途?

另一种方法是对您所拥有的内容略有不同:添加第三个文件,即模板实现/实例化文件.

foo.h文件

// Standard header file guards omitted

template 
class foo
{
public:
    void bar(const T& t);
};

foo.cpp文件

// Always include your headers
#include "foo.h"

template 
void foo::bar(const T& t)
{
    // Do something with t
}

foo-impl.cpp文件

// Yes, we include the .cpp file
#include "foo.cpp"
template class foo;

需要注意的是,您需要告诉编译器编译foo-impl.cpp而不是foo.cpp编译,后者什么都不做.

当然,您可以在第三个文件中有多个实现,或者为您要使用的每种类型提供多个实现文件.

当共享模板化类用于其他用途时,这可以提供更大的灵活性.

此设置还减少了重用类的编译时间,因为您不会在每个转换单元中重新编译相同的头文件.


我认为最好将foo.cpp和foo-impl.cpp解耦。不要在foo-impl.cpp文件中使用#include“ foo.cpp”。相反,应在foo.cpp中添加声明“ extern template class foo <int>;”,以防止编译器在编译foo.cpp时实例化模板。确保构建系统生成两个.cpp文件,并将两个目标文件都传递给链接器。这有很多好处:a)在foo.cpp中很明显没有实例化;b)对foo.cpp的更改不需要重新编译foo-impl.cpp。

6> Red XIII..:

这绝对不是一个讨厌的黑客,但要注意你必须为你想要与给定模板一起使用的每个类/类型(显式模板特化)这样做.如果许多类型请求模板实例化,则.cpp文件中可能有很多行.要解决此问题,您可以在每个使用的项目中使用TemplateClassInst.cpp,以便更好地控制将实例化的类型.显然这个解决方案不会是完美的(也就是银弹),因为你最终可能会破坏ODR :).

推荐阅读
路人甲
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有