【问题标题】:c++ static_assert fails on both branches of an 'if constexpr statement'c++ static_assert 在“if constexpr 语句”的两个分支上都失败
【发布时间】:2021-07-26 07:43:14
【问题描述】:

我试图在编译时确定特定类型是否属于 std::pair 类型。 当我编译下面的代码时,两个分支(即“HERE1”和“HERE2”)上的断言都失败了。 如果我删除 static_asserts 并取消注释打印,我会得到我所期望的: 即 is_pair_type<:value_type> 为“HERE1”,is_pair_type 为“HERE2”。

我猜这意味着编译器无法在编译时评估表达式,但我不明白为什么。

使用:MS VS2019,MSVC 版本 14.29.30037

谢谢。


template< class T >             struct is_pair : std::false_type {};
template< class T1, class T2 >  struct is_pair< std::pair< T1, T2 > > : std::true_type {};
template< class T >             struct is_pair_d : is_pair<typename std::decay<T>::type> {};
// a helper function for value
template<class T> struct is_pair_type {
    static constexpr bool const value = is_pair_d<T>::value;
};

int main()
{
    using T = std::map<int, float>;
    T blabla;

    if constexpr (is_pair_type<T>::value)
    {
        //std::cout << "HERE1" << "\n";
        static_assert(false, "HERE1");
    }
    else
    {
        //std::cout << "HERE2" << "\n";
        static_assert(false, "HERE2");
    }
    ...

【问题讨论】:

    标签: c++ c++17 typetraits static-assert compile-time-type-checking


    【解决方案1】:

    Constexpr if 应该与模板一起使用:

    在模板之外,完全检查丢弃的语句。 if constexpr 不能替代#if 预处理指令:

    void f() {
        if constexpr(false) {
            int i = 0;
            int *p = i; // Error even though in discarded statement
        }
    }
    

    注意:对于所有可能的特化,被丢弃的语句不可能是格式错误的:

    template <typename T>
    void f() {
         if constexpr (std::is_arithmetic_v<T>)
             // ...
         else
           static_assert(false, "Must be arithmetic"); // ill-formed: invalid for every T
    }
    

    您可以将代码包装到一个函数模板中,例如:

    template<class T> struct dependent_false : std::false_type {};
    template <typename T>
    void foo() {
        if constexpr (is_pair_type<T>::value)
        {
            std::cout << "HERE1" << "\n";
            static_assert(dependent_false<T>::value, "HERE1");
        }
        else
        {
            std::cout << "HERE2" << "\n";
            static_assert(dependent_false<T>::value, "HERE2");
        }
    }
    

    然后

    using T = std::map<int, float>;
    foo<T>(); // static_assert fails only on the else part
    

    LIVE

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-13
      • 1970-01-01
      • 2018-02-02
      • 2019-01-26
      • 2014-12-20
      • 2016-05-27
      • 2021-10-17
      • 2015-02-24
      相关资源
      最近更新 更多