Why does the `static_assert` always get invoked?

人盡茶涼 提交于 2019-12-02 17:53:21

问题


If USE_STATIC_ASSERT is 0, this works as expected (getting indexed type from the list). If 1 the static_assert() is always tripped. I would have thought that the static_assert() would only happen if all the typenames were exhausted. Why is this not so?

#define USE_STATIC_ASSERT 1
template <unsigned int I, typename ...Ts>
struct items;

template <typename T, typename ...Ts>
struct items<0, T, Ts...>
{
    typedef T type;
};

template <unsigned int I, typename T, typename ...Ts>
struct items<I, T, Ts...> : items<I-1, Ts...>
{
};

#if USE_STATIC_ASSERT
template <unsigned int I>
struct items<I>
{
    static_assert(false, "Ran out of Ts.");
};
#endif


int main()
{
    cout << is_same<float, items<1, int, float, double>::type>::value << endl;
}

回答1:


Even if the partial specialization of items that contains the static_assert is not instantiated, the compiler is allowed to reject this code according to §14.6 [temp.res]/p8:

Knowing which names are type names allows the syntax of every template to be checked. No diagnostic shall be issued for a template for which a valid specialization can be generated. If no valid specialization can be generated for a template, and that template is not instantiated, the template is ill-formed, no diagnostic required.

To work around that, you can make the expression in static_assert dependent on other class template:

#include <type_traits>

template <unsigned int I>
struct AlwaysFalse : std::false_type {};

template <unsigned int I>
struct items<I>
{
    static_assert(AlwaysFalse<I>{}, "Ran out of Ts.");
    //            ~~~~~~~~~~~~~~~^
};


来源:https://stackoverflow.com/questions/27738971/why-does-the-static-assert-always-get-invoked

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!