使用SFINAE的static_assert
标准在 [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
本质上等于 a static_assert(false, "should not be here");
(我们不能同时是 anint
和 an int
),这是不允许的。另一方面,就 SFINAE 而言,类型,例如,A<double>
格式完美并且可以生成,但会立即引发静态断言失败。这目前在 GCC 8.3 中有效,但鉴于上述标准引用的“格式错误,无需诊断”部分,我想确保它确实应该有效。(注意:这里的工作被定义为意味着static assertion
如果我尝试实例化 aA<double>
并且不进行静默编译,它会抛出失败)
回答
不,这不是为了工作。那不是有效的 C++ 程序。
根据您引用的段落,您的部分专业化的模板定义是格式错误的 NDR。没有可以从中生成的有效专业化。
该标准通常将某些内容指定为格式错误的 NDR,因为在一般情况下可靠地检查它相当于与莱斯定理相矛盾。所以编译器没有义务尝试,但他们可能会尝试一些启发式分析或其他。
GCC 和 Clang 经常会在添加启发式方法时进行更多诊断。我不会试图声称“这是依赖”作为反对的盾牌。代码本身从一开始就无效。