c++ - 是否允许编译器评估静态断言中的重言式

标签 c++ language-lawyer static-assert

<分区>

在模板中提供 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 的实例化,而第二个将成功,如果没有实例化将导致主模板。

第二个 static_assert 显然是重言式,但它“依赖”于 T 以实现预期效果。但这有保证吗?是否允许编译器评估这些重言式?

最佳答案

相关规则是[temp.res]/8 :

Knowing which names are type names allows the syntax of every template to be checked. The program is ill-formed, no diagnostic required, if:

  • no valid specialization can be generated for a template or a substatement of a constexpr if statement within a template and the template is not instantiated, or

  • [...]

两者都是 static_assert示例中的 s 导致程序格式错误,但不需要诊断。编译器当然允许评估任意复杂的表达式,以试图证明无法生成有效的特化,但并不要求他们这样做。 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> .但不要让任何人真正这样做。

关于c++ - 是否允许编译器评估静态断言中的重言式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44345121/

相关文章:

c++ - 如何在编译时检查两种类型是否相同(如果它与 Boost strong typedef 一起使用则加分)

c++ - 如何生成像列表理解这样的 vector

c++ - 是否可以向系统库 header 添加空格?

c++ - 友元函数的参数依赖查找

c++ - 在类模板中没有定义参数的情况下调用 friend 模板函数

c++ - 如何在 constexpr if-else 链中导致静态错误?

c++ - 这个 static_assert 会被触发吗?

c++ - 如何创建 union 类结构?

c++ - 尝试在派生类中使用 spaceship 运算符

c++ - `const &&` 是否绑定(bind)到所有 prvalues(和 xvalues)?