为什么 `static_assert` 总是被调用?
Why does the `static_assert` always get invoked?
如果 USE_STATIC_ASSERT
是 0
,这会按预期工作(从列表中获取索引类型)。如果 1 则 static_assert()
总是跳闸。我原以为 static_assert()
只有在所有 typename
都用完时才会发生。为什么不是这样?
#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;
}
即使未实例化包含 static_assert
的 items
的部分特化,编译器也可以根据 §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.
要解决这个问题,您可以使 static_assert
中的表达式依赖于其他 class 模板:
#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.");
// ~~~~~~~~~~~~~~~^
};
如果 USE_STATIC_ASSERT
是 0
,这会按预期工作(从列表中获取索引类型)。如果 1 则 static_assert()
总是跳闸。我原以为 static_assert()
只有在所有 typename
都用完时才会发生。为什么不是这样?
#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;
}
即使未实例化包含 static_assert
的 items
的部分特化,编译器也可以根据 §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.
要解决这个问题,您可以使 static_assert
中的表达式依赖于其他 class 模板:
#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.");
// ~~~~~~~~~~~~~~~^
};