当链接器可以显式特化时,是否所有编译器都忽略生成的模板代码?
do all compilers ignore generated template code when explicit specializations are available to the linker?
我最近在专门化模板时遇到了一种让我感到不安的情况:
foo:
template <class T>
void foo() {
std::cout << "This is the generic foo" << std::endl;
}
foo.cc:
#include "foo.h"
template <>
void foo<int>() {
std::cout << "This is foo<int>" << std::endl;
}
main.cc:
#include "foo.h"
int main() {
foo<int>();
}
。我编译如下:
g++ -c main.cc
g++ -c foo.cc
g++ -o main main.o foo.o
输出为"This is foo<int>"
。我喜欢这个输出。但是我担心我观察到的可能是gcc独有的(我没有访问其他编译器的权限,所以我无法检查)。
我认为gcc正在做的是:cc被编译,我希望它发出foo调用的泛型代码,因为它不知道foo.cc中的专门化。但是通过与foo连接。O,它使用专门化,因为它具有相同的签名。
但是指望这个不好吗?我担心其他编译器(甚至可能是不同版本的gcc?)在发出模板代码时可能会弄乱它们的签名,以一种与foo链接的方式。o不会像我希望的那样替换通用动作。这种担心合理吗?我读过很多让我感到不安的东西,但没有什么能让我对目前的情况感到自信。
我担心我观察到的可能是gcc独有的(我没有访问其他编译器的权限,所以我无法检查)。
你有充分的理由担心:你的程序是病态的,编译器甚至不需要告诉你!
c++ 11标准第14.7.3/6段规定:
为了使程序具有一致的行为,您的专门化必须从实例化的角度可见。在您的情况下,它不是:您将它降级到其他翻译单元不包含的文件中。如果模板、成员模板或类模板的成员显式特化,则该特化应该在第一次使用可能导致隐式实例化的专门化之前声明发生:在发生这种用法的每个翻译单元中发生;不需要诊断。如果程序没有为显式专门化提供定义,或者以某种方式使用专门化会导致隐式实例化发生,或者成员是虚成员函数,程序格式错误,不需要诊断。永远不会为显式实例生成隐式实例已声明但未定义的专门化
第14.7.3/7段对于不这样做会发生什么非常明确:
函数模板、类模板、成员函数的显式特化声明的位置对于类模板,[…]],可以影响一个程序是否被根据显式专门化声明及其点的相对定位而形成的在上面和下面指定的翻译单元中实例化。在编写专门化时要小心关于其位置;或者让它编译将是一种考验,从而点燃它的自焚。
我想最后一句已经说得很清楚了。
在这里,你应该做的是在出现主模板的任何隐式实例化之前声明你想要引入函数模板的显式专门化。为此,请执行以下操作:foo。
template <class T>
void foo() {
std::cout << "This is the generic foo" << std::endl;
}
template <> void foo<int>(); // Introduce a declaration of your
// explicit specialization right
// after you defined the primary
// template!
通过在主模板定义之后引入声明,可以确保无论主模板在哪里可见,都知道它存在完整的专门化,从而避免了自我牺牲。
- 为什么所有C++编译器都会崩溃或挂起此代码
- 为C++03编译器编写部分unique_ptr,该编译器与较新的编译器在公共代码库上运行
- 与其他编译器相比,相同的代码在工作室Microsoft提供不同的输出
- Visual Studio 中是否有来自代码块的编译器标志的类似物?
- C++ 代码的行为因编译器而异
- 代码未在联机编译器上显示结果
- 在 Azure DevOps 构建管道中使用英特尔C++编译器为 Linux 环境构建C++代码
- 编译器资源管理器(godbolt)如何安全地运行代码?
- 使用特征C++需要哪个代码块编译器?
- GCC 编译器是否应该对涉及 [[fallthrough]] 属性的格式错误的C++代码进行诊断?
- boost::spirit--试图编译大多数简单代码的编译器错误
- 使用其他编译器编译QT代码
- 使用 Mac 终端编译器编译 c++14 代码
- 我最近更改了编译器路径以运行 c++ 代码,但现在我无法运行任何 python 代码。我该如何解决这个问题?
- 编译器是否C++具有相同模板参数集的每个模板类实例生成代码?
- 为什么当我的代码超出函数范围时,"does not name a type"出现编译器错误?
- 如何获得代码::块的C++代码编译器?
- 编译器会自动优化重复代码吗?
- 数字火星编译器(代码::块)无法打开文件'iostream'
- 端口/重新编码真正大和旧的C++编译器代码到Qt或CLI/Mono