如果没有 if-constexpr 成功,触发编译时错误的最佳方法是什么?

Cha*_*ria 4 c++ static-assert type-traits if-constexpr

我有一系列很长的if constexpr语句,如果没有一个成功,我想触发编译时错误。

具体来说,我有一个抽象语法树,我想将其结果转换为我可能需要的一组特定类型。我有 AsInt()、AsDouble() 等正在工作,但我需要能够根据提供的类型更动态地执行此操作。

就目前情况而言,我已经编写了一个模板化的 As() 成员函数,但它的错误检查很笨拙。具体来说,使用静态断言需要一个笨拙的测试条件。这是一个简化版本:

template <typename T>
T As() {
  if constexpr (std::is_same_v<T,int>) return AsInt();
  if constexpr (std::is_same_v<T,double>) return AsDouble();
  ...
  if constexpr (std::is_same_v<T,std::string>) return AsString();

  static_assert( std::is_same_v<T,int>
                 || std::is_same_v<T,double>
                 || ...
                 || std::is_same_v<T,std::string>,
                 "Invalid template type for As()" );
}
Run Code Online (Sandbox Code Playgroud)

如果所有条件都失败,是否有更简单的方法来触发静态断言(或等效方法)?

Bri*_*ian 12

您需要将 s 序列重写if constexpr为链if constexpr ... else if constexpr ...,并让最后一个else子句在“达到”(即未丢弃)时触发编译错误。这可以使用“依赖惯用语”来完成false

if constexpr (std::is_same_v<T,int>) {
    return AsInt();
} else if constexpr (std::is_same_v<T,double>) {
    return AsDouble();
} ... else if constexpr (std::is_same_v<T,std::string>) {
    return AsString();
} else {
    // this is still constexpr, so it will be discarded if any other branch was taken
    static_assert(dependent_false<T>::value, "invalid template type for As()");
}
Run Code Online (Sandbox Code Playgroud)

其中dependent_false定义为:

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

  • @Adam 模板定义不允许包含格式错误的源,无论模板参数如何 - 即使分支可能被丢弃。使用“dependent_false”,编译器无法证明断言会失败,因为可能存在定义“value = true”的“dependent_false”的特殊化。 (4认同)