使用 if constexpr 的条件 constexpr 表达式

Sil*_*ler 2 c++ c++17

假设您有一个调用另一个函数的函数模板,该函数可能是也可能不是函数,constexpr具体取决于模板参数。C++ 允许以任何方式声明被调用者constexpr,只要至少一个可能的实例化产生一个constexpr.

例如:

template <class T>
constexpr bool bar() { return true; }

template <>
bool bar<int>() { return false; }

template <class T>
constexpr bool foo() { return bar<T>(); }

foo<short>();
foo<int>(); // not a constexpr, but compiles anyway
Run Code Online (Sandbox Code Playgroud)

这提供了很好的灵活性,以便我们可以生产constexpr尽可能生成函数调用,但否则会回退到非 constexpr。

然而,我注意到 C++17 并没有同样的灵活性if constexpr

例如:

if constexpr(foo<short>()) { /* do something */ }; // works
if constexpr(foo<int>()) { /* do something */ }; // won't compile, bar<int>() is not constexpr!
Run Code Online (Sandbox Code Playgroud)

我遇到过这样的情况,我想使用它if constexpr来避免实例化某些模板的编译时间开销,但计算的表达式可能并不总是取决于constexpr模板参数。如果条件表达式依赖于模板参数并且模板实例化为非constexpr ,是否有某种原因if constexpr不会“降级”为非constexpr 语句?if就像constexpr函数的行为一样吗?

这仅仅是标准中的任意遗漏(即没有人认为它有用),还是有一些更根本的原因为什么if constexpr不能“降级”为非 constexpr if

Nic*_*las 6

它不会“降级”,其原因与它不会降级的原因相同:

constexpr auto value = expression;
Run Code Online (Sandbox Code Playgroud)

如果您将变量声明为constexpr,那么您就是认真的。你的意思是它的值是一个编译时常量,编译器将执行常量评估来生成它的值。

这同样适用于if constexpr;条件一个常量表达式。if constexpr存在根据特定常量表达式是否产生特定值来在不同代码段之间进行选择。它具有特殊的丢弃机制,允许格式错误的代码在某些情况下不采取的条件下存在。

这里没有“侮辱”,因为不应该。问题实际上不是为什么if constexpr不能“降级”;而是为什么不能“降级”。这就是功能“退化”constexpr 原因。这是函数级别constexpr的奇怪之处,而这种奇怪之处就是为什么我们必须在 C++20 中发明一个全新的关键字来表示“是的,我确实是说这个函数是一个常量表达式”。

  • 同意,问题实际上只是语法。这两种结构的语义本身都是有用的。 (2认同)