【问题标题】:static_assert with SFINAE带有 SFINAE 的 static_assert
【发布时间】:2021-04-24 00:46:26
【问题描述】:

标准在 [temp.res]/8 中说:

对于可以生成有效特化的模板定义,不应发出诊断。如果无法为模板定义生成有效的特化,并且该模板未实例化,则模板定义格式错误,无需诊断。 ... [注:如果模板被实例化,错误将根据本标准中的其他规则进行诊断。准确诊断这些错误的时间是实施质量问题。 ——尾注]

我的问题是:以下是否算作可以生成的有效专业化?

#include <type_traits>

template <typename T, typename Enable = void>
class A;

template <typename T>
class A<T, typename std::enable_if<not std::is_same<T, int>::value>::type>
{
public:
    static_assert(std::is_same<T, int>::value, "should not be here!");
};

一方面,static_assert 本质上等于static_assert(false, "should not be here");(我们不能既不是int 又不是int),这是不允许的。另一方面,就 SFINAE 而言,类型,例如,A&lt;double&gt; 格式完美,可以生成,但会立即抛出静态断言失败。这目前在 GCC 8.3 中有效,但鉴于上述标准引用的“格式错误,无需诊断”部分,我想确保它实际上应该工作. (注意:这里的工作被定义为如果我尝试实例化 A&lt;double&gt; 会抛出 static assertion 失败,如果我不这样做则静默编译)

【问题讨论】:

  • 我很困惑。什么有效?我们在谈论“作品”的什么定义?
  • @StoryTeller-UnslanderMonica:添加了一个括号以希望澄清

标签: c++ c++11 language-lawyer


【解决方案1】:

不,这不是意味着工作。这不是一个有效的 C++ 程序。

根据您引用的段落,您的部分专业化的模板定义是格式错误的 NDR。没有可以从中生成的有效特化。

该标准通常将某些内容指定为格式错误的 NDR,因为在一般情况下对其进行可靠检查将等于与 Rice's theorem 相矛盾。所以编译器没有义务尝试,但他们可能尝试一些启发式分析或其他。

GCC 和 Clang 通常会在添加启发式算法时进行更多诊断。我不会试图声称“这是依赖的”作为反对这一点的盾牌。代码本身从一开始就无效。

【讨论】:

  • 我想我可能对“生成”一个有效的专业化意味着什么感到困惑——如果它足以通过 SFINAE,或者它是否意味着实际上有一个有效的类型可能是允许被实例化。您的回答(以及您对某些编译器拒绝sizeof(T) == 0 的上述答案的评论)似乎表明它是前者,而不是后者。
  • @user11923373 - 规范文本有意引用 template-definition。即,我们正在生成的实际类的蓝图。 [temp.res]/8 的精神是要防止蓝图永远无法产生有效的东西。 SFINAE 有点像红鲱鱼。因为当它失败时,我们无法从 that 模板定义中获得有效的特化。当它通过时,我们仍然会得到一些无效的东西。
猜你喜欢
  • 1970-01-01
  • 2012-08-12
  • 1970-01-01
  • 2015-05-27
  • 1970-01-01
  • 1970-01-01
  • 2018-03-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多