首先要做的事情是:我使用的是C ++ 17,使用Boost :: Hana会很好,因为我还是在我的代码中使用它。
我试图通过在定义类的文件中使用隐式类模板实例化(默认情况下不实例化成员定义)来模拟显式类模板实例化(即,实例化所有成员'定义)模板。如果这听起来很奇怪,请参阅"为什么有人会这样做?"下面为什么我认为这可能是我实际问题的解决方案。
这是我要在mytemplate.hpp
中实例化我的模板的声明:
template<class T>
class MyTemplate {
public:
void foo();
};
这是mytemplate.cpp
中的定义:
#include "mytemplate.hpp"
template<class T>
void
MyTemplate<T>::foo() {}
为确保某些类型Whatever
的所有MyTemplate<Whatever>
成员(在此示例中为MyTemplate<Whatever>::foo()
)的定义已实例化,我认为我需要在命名空间范围内创建一个情境,对于MyTemplate<Whatever>
的每个成员,它都包含:
在上下文中引用特化 这需要完全定义的对象类型,或者类类型的完整性会影响语义 该计划
(C ++ 17标准,17.7.1.1)
我的想法是使用继承:如果类Instantiator
派生自MyTemplate<Whatever>
,则Instantiator
的所有成员的定义必须是目标文件的一部分,无论它们是否被使用或不,因为Instantiator
不是模板 - 或者我认为。这当然也需要实例化类模板的成员。
考虑修改后的mytemplate.cpp
:
#include "mytemplate.hpp"
template<class T>
void
MyTemplate<T>::foo() {}
class Instantiator : public MyTemplate<int> {};
编译它不会产生任何符号:
me@mymachine ~/some/dir $ /usr/bin/g++-7 -g -std=c++17 -o mytemplate.cpp.o -c mytemplate.cpp
me@mymachine ~/some/dir $ nm -a mytemplate.cpp.o
0000000000000000 b .bss
0000000000000000 n .comment
0000000000000000 d .data
0000000000000000 N .debug_abbrev
0000000000000000 N .debug_aranges
0000000000000000 N .debug_info
0000000000000000 N .debug_line
0000000000000000 N .debug_str
0000000000000000 a mytemplate.cpp
0000000000000000 n .note.GNU-stack
0000000000000000 t .text
怎么会这样?为什么Instantiator
(及其成员)不属于输出?
您是否看到任何其他方法强制MyTemplate<Whatever>
的每个成员进行实例化?
在mytemplate.{hpp,cpp}
之外的某个地方,我有一个类列表,包含在一个元组中,如下所示:
using MyClassList = std::tuple<int, char, bool>;
现在我想要为MyTemplate
的模板参数的所有类实例化MyClassList
(及其所有成员)的定义 - 而无需手动编写。基本上,如果我更改MyClassList
的定义,我就不想触及mytemplate.{hpp,cpp}
。因此,我不能使用显式实例化。我也不想在其使用的任何地方加入mytemplate.cpp
,因为我的编译单元的大小似乎已经存在问题。
显然,这意味着我无法逐字使用上述派生类技巧,因为我需要手动列出所有派生类,但该问题应该可以通过递归类模板来解决。