C++ 中 if/else 分支的编译时消除
Compile-time elimination of if/else branch in C++
在下面的代码示例中,if
语句依赖于 bool
模板参数,它是一个编译时常量。编译器以不同方式处理此代码:
MSVC 失败并出现 link 错误(这是我所期望的),因为 else
分支中的模板函数缺少 true
模板参数值的专门化(即使它从未被调用过)。
GCC 和 Clang 都可以正常编译,并且 运行-time 行为是正确的。这显然是因为他们在编译时评估 if
语句并在 linking 之前删除未使用的分支。
问题是哪种行为符合标准(或者它是未定义的行为并且两者都以自己的方式正确)?
#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;
}
所有编译器都正确运行。
您的程序格式错误,不需要诊断,因为您通过调用所需的 Struct<true>::print()
实例化使用 Struct<true>::printIfFalse
在 withTrue.print();
。在 废弃语句 之外使用的函数必须在程序中有定义,请参阅 [basic.def.odr]/4,否则程序 格式错误,无需诊断.
丢弃的语句 是您在模板中使用 if constexpr
并且该语句不在所选分支中时得到的结果。因此,要使程序合式,您可以使用 if constexpr
而不是 if
。这是 C++17 的特性。
在下面的代码示例中,if
语句依赖于 bool
模板参数,它是一个编译时常量。编译器以不同方式处理此代码:
MSVC 失败并出现 link 错误(这是我所期望的),因为
else
分支中的模板函数缺少true
模板参数值的专门化(即使它从未被调用过)。GCC 和 Clang 都可以正常编译,并且 运行-time 行为是正确的。这显然是因为他们在编译时评估
if
语句并在 linking 之前删除未使用的分支。
问题是哪种行为符合标准(或者它是未定义的行为并且两者都以自己的方式正确)?
#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;
}
所有编译器都正确运行。
您的程序格式错误,不需要诊断,因为您通过调用所需的 Struct<true>::print()
实例化使用 Struct<true>::printIfFalse
在 withTrue.print();
。在 废弃语句 之外使用的函数必须在程序中有定义,请参阅 [basic.def.odr]/4,否则程序 格式错误,无需诊断.
丢弃的语句 是您在模板中使用 if constexpr
并且该语句不在所选分支中时得到的结果。因此,要使程序合式,您可以使用 if constexpr
而不是 if
。这是 C++17 的特性。