如何断言constexpr if else子句永远不会发生?

Wei*_*ieh 30 c++ c++17

如果条件为真,我想在非constexpr时引发编译时错误,例如:

if constexpr(condition1){
    ...
} else if constexpr (condition2) {
   ....
} else if constexpr (condition3) {
  ....
} else {
    // I want the else clause never taken. But I heard the code below is not allowed
    static_assert(false);
}

// I'd rather not repeat the conditions again like this:
static_assert(condition1 || condition2 || condition3);
Run Code Online (Sandbox Code Playgroud)

Jan*_*ans 31

您必须使废弃的语句依赖于模板参数

template <class...> constexpr std::false_type always_false{};

if constexpr(condition1){
    ...
} else if constexpr (condition2) {
   ....
} else if constexpr (condition3) {
  ....
} else {       
    static_assert(always_false<T>);
}
Run Code Online (Sandbox Code Playgroud)

这是因为

[temp.res]/8 - 该程序格式错误,无需诊断,如果

无法为模板中的模板或constexpr if语句的子语句生成有效的特化,并且模板未实例化,或者......


son*_*yao 15

这是cppreference.com的解决方法,即使用类型相关的表达式.

注意:对于每个可能的专业化,丢弃的语句都不能格式错误:

这种catch-all语句的常见解决方法是依赖于类型的表达式,该表达式始终为false:

例如

template<class T> struct dependent_false : std::false_type {};
Run Code Online (Sandbox Code Playgroud)

然后

static_assert(dependent_false<T>::value);
Run Code Online (Sandbox Code Playgroud)

  • 讽刺真的,因为这正是这给了我们!愚蠢的语言. (5认同)

Sha*_*our 9

在 C++23 中,这个问题的答案发生了变化。论文P2593:允许 static_assert(false)已在2023-02 Issaquah 会议上被接受。我们现在可以使用OP想要使用的习语。

我们可以从接受的措辞中看到,dcl.pre p10已被修改,因此在模板定义上下文static_assert中没有任何影响,并且temp.res p6已被修改,因此它不再格式错误,如果所有专业化都失败,则不需要诊断。static_assert

它还添加了以下示例:

template <class T>
  void f(T t) {
    if constexpr (sizeof(T) == sizeof(int)) {
      use(t);
    } else {
      static_assert(false, "must be int-sized");
    }
  }
  
  void g(char c) {
    f(0); // OK
    f(c); // error: must be int-sized
  }
  
Run Code Online (Sandbox Code Playgroud)