C++ - 为什么此处需要 'template' 关键字?
C++ - Why is the 'template' keyword required here?
我有以下代码:
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;
}
当同时使用 gcc 9.2 和 clang (9.0) 构建它时,由于调用 fun
需要 template
关键字,我遇到了编译错误。 Clang 显示:
error: use 'template' keyword to treat 'fun' as a dependent template name
s.fun<int>();
^
template
我不明白为什么编译器认为 fun
是 f
上下文中的从属名称,因为 f
本身不是模板。如果我将 C
更改为常规 class 而不是模板,错误就会消失;但是,我不明白为什么首先会出现错误,因为 S
和 f
都不依赖于 TC
.
奇怪的是,MSVC 19.22 可以很好地编译它。
注意
在投票关闭作为 Where and why do I have to put the "template" and "typename" keywords? 的欺骗之前,请考虑这是一个特殊情况,即使 S
确实是一个从属名称,在 f
的上下文中它也不会如果不是因为它们是当前实例化的成员,则它们是依赖的。
fun
可能是也可能不是模板函数(或者根本不存在),具体取决于 class C
.
的模板参数
那是因为你可以专精S
(而不专精C
):
template <> struct C<int>::S {};
因为编译器在第一次查看 class C
时(在替换模板参数之前)想知道 fun
是否是模板,所以需要 template
。
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
}
s.a<0>(i)
被解析为包含两个比较操作 <
和 >
的表达式,这对 #1 没问题但对 #2 失败。
如果这是 changed 到 s.template a<0>(i)
,则 #2 正常,#1 失败。因此 template
关键字在这里绝不是多余的。
MSVC capable 在同一程序中以两种方式解释表达式 s.a<0>(i)
。但根据标准,这是不正确的;每个表达式应该只有一个解析供编译器处理。
我有以下代码:
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;
}
当同时使用 gcc 9.2 和 clang (9.0) 构建它时,由于调用 fun
需要 template
关键字,我遇到了编译错误。 Clang 显示:
error: use 'template' keyword to treat 'fun' as a dependent template name
s.fun<int>();
^
template
我不明白为什么编译器认为 fun
是 f
上下文中的从属名称,因为 f
本身不是模板。如果我将 C
更改为常规 class 而不是模板,错误就会消失;但是,我不明白为什么首先会出现错误,因为 S
和 f
都不依赖于 TC
.
奇怪的是,MSVC 19.22 可以很好地编译它。
注意
在投票关闭作为 Where and why do I have to put the "template" and "typename" keywords? 的欺骗之前,请考虑这是一个特殊情况,即使 S
确实是一个从属名称,在 f
的上下文中它也不会如果不是因为它们是当前实例化的成员,则它们是依赖的。
fun
可能是也可能不是模板函数(或者根本不存在),具体取决于 class C
.
那是因为你可以专精S
(而不专精C
):
template <> struct C<int>::S {};
因为编译器在第一次查看 class C
时(在替换模板参数之前)想知道 fun
是否是模板,所以需要 template
。
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
}
s.a<0>(i)
被解析为包含两个比较操作 <
和 >
的表达式,这对 #1 没问题但对 #2 失败。
如果这是 changed 到 s.template a<0>(i)
,则 #2 正常,#1 失败。因此 template
关键字在这里绝不是多余的。
MSVC capable 在同一程序中以两种方式解释表达式 s.a<0>(i)
。但根据标准,这是不正确的;每个表达式应该只有一个解析供编译器处理。