c++ - C++ - 为什么这里需要“模板”关键字?
问题描述
我有以下代码:
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) 构建它时,由于template
调用fun
. 铿锵声显示:
error: use 'template' keyword to treat 'fun' as a dependent template name
s.fun<int>();
^
template
我不明白为什么编译器认为fun
是上下文中的依赖名称f
,因为f
它本身不是模板。如果我改为C
普通类而不是模板,错误就会消失;但是,我不明白为什么首先应该出现错误,因为既不S
也不f
依赖TC
.
奇怪的是,MSVC 19.22 编译得很好。
笔记
在投票结束之前,我必须在哪里以及为什么要放置“模板”和“类型名”关键字?请考虑这是一种特殊情况,即使S
确实是一个依赖名称,f
如果不是因为它们是当前实例化的成员,在上下文中它也不会依赖。
解决方案
考虑:
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 失败。
如果将其更改为,s.template a<0>(i)
则 #2 正常,而 #1 失败。因此,这里的template
关键字永远不会是多余的。
MSVC能够s.a<0>(i)
在同一程序中以两种方式解释表达式。但是根据标准这是不正确的;每个表达式应该只有一个解析供编译器处理。
推荐阅读
- c - 无限输入直到出现空白
- python - 使用 sns.pairplot 色调
- sql - 使用 PostgreSQL 打印星行?
- php - 可以在没有模型的情况下注册 Laravel 策略吗?
- python - 基于统计数据的 PRNG (Python)
- jquery - 如何防止用户在可滚动文本区域的最底部打字?
- reactjs - 反应路由器链接不刷新页面
- javascript - isPalindrome() 函数在测试用例上失败
- function - PowerShell 错误:计算机名称在自定义函数中无效
- react-native - React Navigation 4:重置嵌套在 DrawerNavigator 中的 StackNavigator