【问题标题】:Are compilers allowed to evaluate tautologies in static assert [duplicate]是否允许编译器在静态断言中评估重言式 [重复]
【发布时间】:2017-06-03 14:45:51
【问题描述】:

在模板中提供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 以达到预期的效果。但这能保证吗?是否允许编译器评估这些重言式?

【问题讨论】:

  • 但是可能没有定义这样的特化,编译器在处理反重言式时不必知道未来的代码......
  • 恕我直言,代码的同一部分不能同时根据(可能是遥远的)上下文形成良好和错误的形式......这会给已经重载的编译器带来额外的困难......
  • @bolov 如果我现在可以结束这个问题:(

标签: c++ language-lawyer static-assert


【解决方案1】:

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

知道哪些名称是类型名称可以检查每个模板的语法。该程序格式错误,不需要诊断,如果:

  • 不能为模板或 constexpr 的子语句生成有效的特化,如果模板内的语句和模板未实例化,或

  • [...]

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

【讨论】:

  • 这就是我害怕的。我想除非你是编译器作者,否则写这样的东西是不明智的?
  • 等一下,“无法为模板生成有效的特化”,这不是指“不存在T 以使S&lt;T&gt; 有效”吗?但在示例中,S&lt;int&gt; 是有效的,因此程序格式正确?
  • @PasserBy:这篇文章与你的非常相关:stackoverflow.com/questions/5246049/…
  • @PasserBy 没有。这句话指的是主模板的假设实例,没有考虑专业化。在我链接的副本中有两个关于此问题的扩展讨论的答案。
猜你喜欢
  • 2017-05-05
  • 2013-09-06
  • 1970-01-01
  • 2020-07-19
  • 2011-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-17
相关资源
最近更新 更多