【问题标题】:Best way to trigger a compile-time error if no if-constexpr's succeed?如果没有 if-constexpr 成功,触发编译时错误的最佳方法是什么?
【发布时间】:2021-10-08 20:37:19
【问题描述】:

我有一长串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()" );
}

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

【问题讨论】:

    标签: c++ typetraits static-assert if-constexpr


    【解决方案1】:

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

    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()");
    }
    

    其中dependent_false 定义为:

    template <class T> struct dependent_false : std::false_type {};
    

    【讨论】:

    • 您能解释一下为什么dependent_false 有用吗?为什么不只是static_assert(false, "invalid template type for As()");?
    • @Adam 模板定义不允许包含格式错误的源代码,无论模板参数如何 - 即使分支可能被丢弃。对于dependent_false,编译器无法证明断言会失败,因为可能存在定义value = true 的dependent_false 的特化。
    • 到位,完美运行!我仍然需要一些直觉来开发周围的模板和 constexpr,但这种技术现在非常有意义。
    猜你喜欢
    • 1970-01-01
    • 2019-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-21
    • 2017-05-01
    • 1970-01-01
    相关资源
    最近更新 更多