考虑以下代码:
#include <type_traits>
template <typename T> struct A
{
static_assert(!std::is_same_v<int, T>);
};
template<typename T> struct B
{
void foo()
{
A<int>{};
}
};
int main() {}
它来自俄语StackOverflow上的this question,询问其是否有效。
我尝试引用此内容:
[temp.res]/8.1
8 可以在任何实例化之前检查模板的有效性。 [注意:知道哪些名称是类型名称,这样就可以检查每个模板的语法。 —注释] 该程序格式不正确,无需进行诊断,如果:
(8.1) — 如果模板中的语句未被实例化,则无法为模板或constexpr的子语句生成有效的专业化版本,或者< / p>
...
(重点是我的)
由于无法为foo()
生成有效的专业化,因此我认为该代码段的格式错误,即NDR。
但是我被告知[temp.res]/8.1
不适用,因为foo()
本身不是模板成员函数。
cppreference将模板类的非模板成员函数称为“模板实体”,但不清楚是否可以将它们本身视为模板。
因此,问题是:标准是否将模板类的非模板成员本身视为“模板”?
答案 0 :(得分:9)
这实际上是CWG issue 1253
通用非模板成员
部分:17.8 [temp.spec] 状态:起草 Submitter :Nikolay Ivchenkov Date :2011- 03-06
标准中的许多语句仅适用于模板,例如, 17.7 [temp.res]第8段:
如果无法为模板定义生成有效的专业化名称, 并且该模板未实例化,则模板定义为 格式错误,无需诊断。
这显然应该适用于类的非模板成员函数 模板,而不仅仅是模板本身。术语应为 建立以引用这些实际上不是的通用实体 模板。
它似乎仍在起草中。但我认为,像问题一样,OP 中的代码也应采用格式错误的NDR。即使从不使用成员函数(因此也永远不会实例化其完整定义),它甚至也无法假设地实例化,这使其属于错误[temp.res] / 8的范畴。