【发布时间】:2021-03-23 11:35:55
【问题描述】:
我遇到了关于模板重载解析的有趣行为,它在发布和调试构建之间有所不同。我希望能够理解编译器/链接器使用的规则,使其以这种方式运行。
我试着挖掘了一下,这就是我想出的:
S.h
#pragma once
#include <cstdint>
#include <iostream>
enum class Enumeration : uint32_t {
A = 0,
B
};
struct S {
template<typename T>
bool func(Enumeration en) {
std::cout << "enum nonspec\n";
return func<T>(static_cast<uint32_t>(en));
}
template<typename T>
bool func(uint32_t en) {
std::cout << "uint32_t nonspec\n";
return func<T>(en);
}
};
S.cpp
#include "S.h"
template<>
bool S::func<float>(uint32_t en) {
std::cout << "float specialization\n";
return en;
}
template<>
bool S::func<uint32_t>(uint32_t en) {
std::cout << "uint32_t specialization\n";
return en - 1;
}
main.cpp
#include "S.h"
int main() {
S s;
Enumeration a = Enumeration::B;
s.func<float>(a);
return 0;
}
我已经尝试编译各个编译单元(S.cpp.o、main.cpp.o 和生成的二进制文件)。 我发现结果完全取决于 main.cpp.o 编译的优化级别。
-O0 的输出是 enum nonspecfloat specialization。
-O1 的输出是enum nonspecuint32_t nonspecuint32_t nonspecfloat specialization。
使用-O2 或-O3,输出为enum nonspec
然后无限递归uint32_t nonspec。
我检查了目标文件,-O0 有 0000000000000000 W bool S::func<float>(Enumeration)0000000000000000 W bool S::func<float>(unsigned int),-O1 只有 0000000000000000 W bool S::func<float>(unsigned int),
而-O3 没有任何符号。
使用的编译器:gcc 版本 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)
使用的链接器:ldd (Ubuntu GLIBC 2.27-3ubuntu1.3) 2.27
我想我明白会发生什么,但我想知道这种行为是否基于任何规则。
【问题讨论】:
-
您的专业化(声明)在其用法中不可见 -> 格式错误的 NDR。
-
然后推理UB,格式错误的程序是没有意义的。
-
是的,似乎可行的是 UB、IFNDR 的可能输出。
标签: c++ templates linker compiler-optimization