c++ static_assert 在 'if constexpr statement' 的两个分支上都失败

c++ static_assert fails on both branches of an 'if constexpr statement'

我试图在编译时确定特定类型是否属于 std::pair 类型。 当我编译下面的代码时,我在两个分支(即“HERE1”和“HERE2”)上都断言失败。 如果我删除 static_asserts 并取消注释打印,我会得到我期望的结果: 即 is_pair_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");
    }
    ...

Constexpr if 应该使用模板:

Outside a template, a discarded statement is fully checked. if constexpr is not a substitute for the #if preprocessing directive:

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

Note: the discarded statement can't be ill-formed for every possible specialization:

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