注:几个相关问题(例如,这一个)最终被标记为这个问题的副本。我知道这个特别的问题,并在相应的答案中遵循解决办法。但是,不同的编译器产生不同的行为,我不知道为什么。
我的库具有一个类模板,我希望为库中的某些模板参数提供实例,因为模板需要一些重要的编译时间。类模板可以如下所示(stack.hpp)
#ifndef MY_STACK
#define MY_STACK
template<class T>
class stack
{
public:
stack();
};
#endif它的实现驻留在相应的stack.tpp文件中。
#ifndef MY_STACK_TPP
#define MY_STACK_TPP
#include <iostream>
template<class T>
stack<T>::stack()
{
std::cout << "My stack constructor!" << std::endl;
}
#endif由于我只想提供对某些模板参数的支持,所以我的stack.cpp创建了以下显式模板实例:
#include "stack.hpp"
template class stack<double>;
template class stack<char>;
#include "stack.tpp"这是用g++和clang++编译的,但是结果共享库的符号不同:
g++ -std=c++11 -c stack.cpp -o stack.so
nm -C stack.so | grep stack
0000000000000049 t _GLOBAL__sub_I_stack.cpp
0000000000000000 W stack<char>::stack()
0000000000000000 W stack<char>::stack()
0000000000000000 n stack<char>::stack()
0000000000000000 W stack<double>::stack()
0000000000000000 W stack<double>::stack()
0000000000000000 n stack<double>::stack()与
clang++-7 -std=c++11 -c stack.cpp -o stack.so
nm -C stack.so | grep stack
0000000000000050 t _GLOBAL__sub_I_stack.cpp在我的应用程序中,这样一个显式实例化类的构造函数不是使用clang++找到的,但是它在g++中工作得很好。我想这个基本的MWE给出了原因。有人能告诉我如何使用clang++获取类模板的构造函数符号吗?
发布于 2020-02-14 12:28:26
这个程序格式很好。
引用[temp.explicit]/1 mine
类、函数、变量或成员模板专门化可以从其模板显式实例化。成员函数、成员类或类模板的静态数据成员可以从与其类模板关联的成员定义显式实例化。。。
并引用[temp.explicit]/9 mine的话
显式实例化定义(命名为类模板专门化)显式实例化类模板专门化和是仅在实例化点定义的成员的显式实例化定义。
因此,在OPs示例中,stack<T>的显式实例化定义将不包括构造函数的显式实例化定义,因为stack<T>的显式实例化定义放在通过.tpp包含提供it构造函数定义之前。
引用[temp.point]/8 mine
函数模板的专门化、成员函数模板的或类模板的成员函数或静态数据成员的,可以在翻译单元中具有多个实例化点,并且除了上述实例化点外,对于在翻译单元内具有实例化点的任何此类专门化,翻译单元的结束也被视为实例化点。对于类模板的专门化,在翻译单元内至多有一个实例化点。对任何模板的专门化可能在多个翻译单元中具有实例化点。如果两个不同的实例化点根据单一定义规则赋予模板专门化不同的含义,则程序的格式不正确,不需要诊断。
因此,对于stack.cpp包含两个不同实例化点的情况,以及其中一个在包含stack.tpp之前和之后的情况下,程序是不正确的。
但是,这里有点棘手,因为实例化的点取决于如何使用类模板及其成员函数(/constructor)。正如上面引用的[temp.explicit]/9所述,stack<T>的显式实例化不会导致其构造函数的显式实例化定义,我们需要回到[temp.point]获得详细信息,特别是第1、2和4条,关于何时使用上下文将导致包含stack.tpp之前的实例化点。
问题中的独立例子不包括在这些案例中,因此程序us not 的格式不正确。
GCC对clang:看似不同的实例化行为?
有人能告诉我如何使用clang++获取类模板的构造函数符号吗?
由于构造函数从未被使用过,因此它根本不应该(需要)实例化,但是看起来(从操作符号转储) GCC无论如何都是这样做的(这并不违法),而clang却没有。如果在包含track.tpp之后使用/引用构造函数,GCC和clang自然都会实例化它(用于特定的专门化),因为它们是这样做的。
https://stackoverflow.com/questions/60225945
复制相似问题