【发布时间】:2019-05-10 14:30:47
【问题描述】:
考虑以下代码:
#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 if 语句的子语句且模板未实例化,或
...
(强调我的)
由于无法为 foo() 生成有效的特化,我推断 sn-p 格式不正确,NDR。
但有人告诉我[temp.res]/8.1 不适用,因为foo() 本身不是模板成员函数。
cppreference 将模板类的非模板成员函数称为“模板化实体”,但是否可以将其视为模板本身似乎还不清楚。
因此,问题是:标准是否认为模板类的非模板成员本身就是“模板”?
【问题讨论】:
-
这不是和什么依赖模板参数和什么不依赖有关吗?
A<int>总是相同的东西,不管B被实例化时给出的模板参数T是什么。编译器将能够识别出上述构造将失败。另一方面,如果你有A<T>{},那么它依赖于模板参数T(B)。在实例化发生之前,编译器不会努力识别T的哪些值会失败,哪些不会。可能是 所有 个可能的T值导致错误。 -
[temp.mem.func]/1 中的一个(不可否认的非规范性)示例显示了一个具有三个成员函数的类模板,并说代码“声明了三个函数模板”。所以至少作者的意图似乎是将成员函数视为模板。
-
反对“类模板的成员就是模板”:[temp]/9[temp.names]/2[temp.dep.expr]/3.6[temp.expl.spec]/6
标签: c++ language-lawyer