Igo*_*hov 12 c++ templates compiler-optimization template-specialization language-lawyer
在下面的代码示例中,if语句依赖于bool模板参数,它是一个编译时常量。编译器以不同的方式处理此代码:
MSVC 因链接错误而失败(这是我所期望的),因为else分支中的模板函数缺乏true模板参数值的专业化(即使它从未被调用)。
GCC 和 Clang 编译时都没有问题,并且运行时行为是正确的。这显然是因为它们if在编译时评估语句并在链接之前删除未使用的分支。
问题是哪种行为符合标准(或者它是未定义的行为并且两者都以自己的方式正确)?
#include <iostream>
template<const bool condition>
struct Struct
{
void print()
{
if (condition)
{
std::cout << "True\n";
}
else
{
printIfFalse();
}
}
private:
void printIfFalse();
};
template <>
void Struct<false>::printIfFalse()
{
std::cout << "False\n";
}
int main()
{
Struct<true> withTrue{};
withTrue.print();
Struct<false> withFalse{};
withFalse.print();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
wal*_*nut 14
所有编译器的行为都正确。
你的程序是形成不良的,没有诊断需要,因为你ODR-使用Struct<true>::printIfFalse过的实例Struct<true>::print()从呼叫所需withTrue.print();。在废弃语句之外使用 odr 的函数必须在程序中有定义,参见[basic.def.odr]/4,否则程序格式错误,无需诊断。
一个废弃的语句是你所得到的,如果你使用if constexpr的模板和声明是不是在选择分支。所以,你可以做,使良好形成的方案是使用if constexpr替代if。这是一个 C++17 特性。