gpt4 book ai didi

c++ - 使用 clang 显式 C++ 模板实例化

转载 作者:行者123 更新时间:2023-12-02 03:34:05 26 4
gpt4 key购买 nike

注意:几个相关问题(例如 this one )最终被标记为 this question 的重复项。我知道这个特定问题并遵循相应答案中的解决方案。但是,不同的编译器会产生不同的行为,我不知道为什么。

我的库具有一个类模板,我想为库中的某些模板参数提供实例,因为该模板需要一些重要的编译时间。类模板可能如下所示 (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++ 获取类模板的构造函数符号?

最佳答案

该程序格式良好

引用[temp.explicit]/1[强调我的]:

A class, function, variable, or member template specialization can be explicitly instantiated from its template. A member function, member class or static data member of a class template can be explicitly instantiated from the member definition associated with its class template. [..]

并且,引用 [temp.explicit]/9 [强调我的]:

An explicit instantiation definition that names a class template specialization explicitly instantiates the class template specialization and is an explicit instantiation definition of only those members that have been defined at the point of instantiation.

因此,在 OP 示例中,stack<T> 的显式实例化定义将不包括构造函数的显式实例化定义,因为 stack<T> 的显式实例化定义位于提供 it 构造函数的定义之前。通过 .tpp include。

引用 [temp.point]/8 [强调我的]:

A specialization for a function template, a member function template, or of a member function or static data member of a class template may have multiple points of instantiations within a translation unit, and in addition to the points of instantiation described above, for any such specialization that has a point of instantiation within the translation unit, the end of the translation unit is also considered a point of instantiation. A specialization for a class template has at most one point of instantiation within a translation unit. A specialization for any template may have points of instantiation in multiple translation units. If two different points of instantiation give a template specialization different meanings according to the one-definition rule, the program is ill-formed, no diagnostic required.

因此,对于 stack.cpp 包含两个不同实例化点的情况,并且一个在 stack.tpp 包含之前,一个在包含 stack<T> 之后,则程序格式错误。

但是,这里变得有点棘手,因为实例化点取决于类模板及其成员函数(/构造函数)的使用方式。正如上面引用的 [temp.explicit]/9 所涵盖的,stack.tpp 的显式实例化不会导致其构造函数的显式实例化定义,相反,我们需要依靠 [temp.point] 来获取详细信息,特别是第 1、2 和 4 条。 它的使用上下文将在包含 track.tpp 之前导致实例化点。

问题中的独立示例不属于任何这些情况,因此该程序格式不正确。

GCC 与 clang:看似不同的实例化行为?

Can anyone tell me how I can get the constructor symbols for my class template using clang++?

由于构造函数从未被使用过,所以它根本不应该(需要)被实例化,但似乎(从 OP 符号转储来看)GCC 无论如何都会这样做(这不是非法的),而 clang 则不然。如果在包含 ojit_code 之后使用/引用构造函数,那么 GCC 和 clang 都会自然地实例化它(对于所使用的特定特化),因为它们随后需要这样做。

关于c++ - 使用 clang 显式 C++ 模板实例化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60225945/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com