c++ - 使用 SFINAE 的 static_assert

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

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

No diagnostic shall be issued for a template definition for which a valid specialization can be generated. If no valid specialization can be generated for a template definition, and that template is not instantiated, the template definition is ill-formed, no diagnostic required. ... [ Note: If a template is instantiated, errors will be diagnosed according to the other rules in this Standard. Exactly when these errors are diagnosed is a quality of implementation issue. — end note ]


我的问题是:以下是否算作可以生成的有效特化?
#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"); (我们不能同时是 intint),这是不允许的。另一方面,就 SFINAE 而言,类型,例如,A<double>格式完美,可以生成,但会立即引发静态断言失败。这目前在 GCC 8.3 中有效,但鉴于上述标准引用的“格式错误,无需诊断”部分,我想确保它实际上是 应该工作。 (注意:这里的工作被定义为意味着如果我尝试实例化 static assertion 会抛出 A<double> 失败,如果我不实例化则静默编译)

最佳答案

不,这不是为了工作。那不是有效的 C++ 程序。
根据您引用的段落,您的部分特化的模板定义是格式错误的 NDR。没有可以从中生成的有效特化。
该标准通常将某些内容指定为格式错误的 NDR,因为在一般情况下对其进行可靠的检查相当于与 Rice's theorem 相矛盾。 .所以编译器没有义务尝试,但他们可能会尝试一些启发式分析或其他。
GCC 和 Clang 经常会在添加启发式方法时进行更多诊断。我不会试图声称“这是依赖”作为反对的盾牌。代码本身从一开始就无效。

关于c++ - 使用 SFINAE 的 static_assert,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65796231/

相关文章:

c++ - 初始化器究竟是什么时候被临时销毁的?

c++ - 包含内部模板类的 C++ 模板类构造函数的正确语法

multithreading - .obj 中已定义的多线程函数

c++ - 将转发 lambda 转换为函数指针

c++ - 函数原型(prototype)中的不同参数名称

c++ - clang++ (3.3/Xcode) 中 std::function 的定义在哪里

c++ - C++ 中的列式文本抓取

c++ - 访问模板类的 protected 属性

c++ - Ada 记录缺少的功能

c++ - 为什么 CRITICAL_SECTION 性能在 Win8 上变差