【问题标题】:if constexpr and dependent false static_assert is ill formed?如果 constexpr 和相关的 false static_assert 格式不正确?
【发布时间】:2020-01-08 17:50:02
【问题描述】:

related questionstatic_assert 中提供了与类型无关的false 的示例:

template<class T> void foo()
{
    if constexpr(false)
        static_assert(false);
}

但是,如果同样的事情适用于依赖类型的false,我更担心。以下是标准中的相关引述:

如果无法为模板或模板中的 constexpr if 语句的子语句生成有效的特化,则程序格式错误,不需要诊断,并且模板未实例化。 § 13.7/8.1

这让我很惊讶,因为我经常看到以下成语:

template<class T> void foo()
{
    if constexpr(cond)
        // ...
    else
        static_assert(!std::is_same_v<T, T>);
}

事实上,cppreference 甚至提供了同样的东西的an example

template<class T> struct dependent_false : std::false_type {};
template<class T> void foo()
{
    if constexpr (cond)
        // ...
    else
        static_assert(dependent_false<T>::value);
}

据我了解,在这两种情况下,都无法为相关的 if constexpr 子语句生成有效的专业化,因此格式不正确,不需要诊断。我说的对吗?

【问题讨论】:

标签: c++ language-lawyer


【解决方案1】:

永远无法为相关的if constexpr 子语句生成有效的特化

没有。

如果您首先专门化 dependent_false,您可以拥有该分支的有效专业化:

template <> struct dependent_false<int> : std::true_type {};
///
foo<int>(); // <-- A valid specialization for the `else` branch is possible here

可以创建这样的专业化(即使您没有)这一事实使static_assert(dependent_false&lt;T&gt;::value); 格式良好。

另一方面,static_assert(!std::is_same_v&lt;T, T&gt;); 是格式错误的 NDR,因为不允许使用来自 std:: 的专门模板。

【讨论】:

  • 这不是说cppreference的例子其实很糟糕吗?因为那里没有int 的专业化。此外,我们希望每种类型都为 false,int 不应该是一个例外。所以一个更好的类型是 Jarod42 使用的那个,decltype([](){})
  • @geza 我并不是说您需要创建dependent_false 的特化来使代码格式正确。我是说它格式正确,因为您可以创建一个专业化。
  • @geza 为清楚起见已编辑。
  • 嗯。再想一想,是不是这样,如果cond 永远是真的,那我们就很好了?没有必要让 static_assert 的条件永远为真,因为如果cond 可以为真,则已经存在有效的特化。
  • 另一方面,如果cond 总是为假,那么我们必须有一个dependent_false 特化,它给出真,因为如果我们没有,所有特化都是无效的。所以在这种情况下,理论上我们可以加一个是不够的,但我们需要加一个。
猜你喜欢
  • 2016-09-16
  • 2016-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-28
相关资源
最近更新 更多