Mar*_*tin 10 c++ templates dependent-name language-lawyer
我有以下代码:
template <typename TC>
class C
{
struct S
{
template <typename TS>
void fun() const
{}
};
void f(const S& s)
{
s.fun<int>();
}
};
// Dummy main function
int main()
{
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当使用 gcc 9.2 和 clang (9.0) 构建它时,由于template调用fun. Clang 显示:
error: use 'template' keyword to treat 'fun' as a dependent template name
s.fun<int>();
^
template
Run Code Online (Sandbox Code Playgroud)
我不明白为什么编译器认为fun是 上下文中的依赖名称f,因为f它本身不是模板。如果我改为C普通类而不是模板,错误就会消失;但是,我不明白为什么首先应该出现错误,因为既不S也不f依赖于TC.
奇怪的是,MSVC 19.22 编译得很好。
在投票结束之前,我为什么要放置“模板”和“类型名称”关键字?请考虑这是一种特殊情况,即使S它确实是一个依赖名称,在上下文中f也不会依赖,如果不是因为它们是当前实例化的成员。
eca*_*mur 11
考虑:
template<typename T>
struct C
{
struct S
{
int a = 99;
};
void f(S s, int i)
{
s.a<0>(i);
}
};
template<>
struct C<long>::S
{
template<int>
void a(int)
{}
};
int main()
{
C<int>{}.f({}, 0); // #1
C<long>{}.f({}, 0); // #2
}
Run Code Online (Sandbox Code Playgroud)
s.a<0>(i)被解析为包含两个比较操作<and的表达式>,这对 #1 很好,但对 #2 失败。
如果更改为,s.template a<0>(i)则#2 正常,#1 失败。因此,template关键字在这里永远不会多余。
MSVC能够s.a<0>(i)在同一程序中以两种方式解释表达式。但根据标准,这是不正确的;每个表达式应该只有一个解析器供编译器处理。
fun可能是也可能不是模板函数(或可能根本不存在)取决于 的模板参数class C。
那是因为您可以专攻S(无需专攻C):
template <> struct C<int>::S {};
Run Code Online (Sandbox Code Playgroud)
因为编译器fun在第一次查看时class C(在替换模板参数之前)想知道是否是模板,这template是必需的。
| 归档时间: |
|
| 查看次数: |
554 次 |
| 最近记录: |