在模板中提供static_assert
通常很有帮助。在模板不应该以某种方式实例化的情况下,我经常这样做
template<typename T, typename = void>
struct S
{
static_assert(false, "Unconditional error");
static_assert(sizeof(T) != sizeof(T), "Error on instantiation");
};
template<typename T>
struct S<T, std::enable_if_t<std::is_integral_v<T>>>
{
// ...
};
即使没有static_assert
的实例化,第一个S
也会立即失败,而如果没有实例化会导致主模板,则第二个{000}会成功。
第二个static_assert
显然是一个重言式,但它依赖于&#34;在T
上,以达到预期的效果。但这有保证吗?是否允许编译器评估这些重言式?
答案 0 :(得分:9)
相关规则为[temp.res]/8:
知道哪些名称是类型名称允许检查每个模板的语法。该程序格式错误,无需诊断,如果:
无法为模板或模板中的constexpr if语句的子语句生成有效的专业化,且模板未实例化,或
[...]
示例中的两个static_assert
导致程序格式错误,但不需要诊断。编译器肯定是允许来评估任意复杂的表达式,以试图证明不能生成有效的特化,但是他们不需要这样做。 false
当然是一个容易立即验证的案例,所以它被诊断出来就不足为奇了。
始终发布诊断的一种常见方法是:
// never specialize me!
template <typename T>
struct always_false : std::false_type { };
template <typename T>
constexpr bool always_false_v = always_false<T>::value;
template<typename T, typename = void>
struct S {
static_assert(always_false_v<T>, "Unconditional error");
};
always_false
可以假设专门针对特定的T
来产生true_type
,因此可以假设有效的专业化S<T>
。但是,不要让任何人真正这样做。