c++ - typename c++ 和编译顺序
问题描述
在这篇文章https://en.wikipedia.org/wiki/Typename中,涉及到关键字 Typename 的使用,是这样写的:
template <typename T>
void foo(const T& t)
{
// declares a pointer to an object of type T::bar
T::bar * p;
}
struct StructWithBarAsType {
typedef int bar;
};
int main() {
StructWithBarAsType x;
foo(x);
}
在 StructWithBarAsType 中依赖 bar 实际上是一种类型这一事实并没有帮助,因为 foo() 可以在看到 StructWithBarAsType 之前很久就被编译。
我不明白为什么 foo() 可以在 StructWithBarAsType 之前编译很久,在这种情况下可能是这样吗?
解决方案
当编译器解析 C++ 文件时,它通常会构建一个标识符到类型的符号表。这在调用模板时很重要,因为 C++ 编译器本质上会进行“替换检查”以确保“一切正常”。
问题是这个模棱两可的陈述:
T::bar * p;
这可以解释为:
T
命名类型的静态成员变量bar
乘以p
:? operator*(? T::bar, ? p)
- 声明类型
T::bar*
为 name的指针p
。
这在解析时会产生某种歧义,并导致编译器错误:
g++ main.cpp && ./a.out
main.cpp: In function 'void foo(const T&)':
main.cpp:9:13: error: 'p' was not declared in this scope
9 | T::bar * p;
| ^
main.cpp: In instantiation of 'void foo(const T&) [with T = StructWithBarAsType]':
main.cpp:14:9: required from here
main.cpp:9:11: error: dependent-name 'T::bar' is parsed as a non-type, but instantiation yields a type
9 | T::bar * p;
main.cpp:9:11: note: say 'typename T::bar' if a type is meant
main.cpp:9:11: error: dependent-name 'T::bar' is parsed as a non-type, but instantiation yields a type
为了清除此解析错误,C++ 对“信号”进行了“语法修改”,表明模板中的标识符旨在成为类型名称而不是变量名称。这种“语法修改以以下形式出现typename
:
struct StructWithBarAsType {
typedef int bar;
};
template <typename T>
void foo(const T& t)
{
// declares a pointer to an object of type T::bar
typename T::bar * p;
}
int main() {
StructWithBarAsType x;
foo(x);
}
这会编译。
请注意,与 C++ 中的解析相关的类似问题也会发生。查看最令人头疼的解析。
推荐阅读
- java - 将测试自动化代码与没有黄瓜/小黄瓜的书面测试用例联系起来
- r - R 对象不存在(未定义),但 R 可以检索值
- angular - 如何正确使用具有反应形式、ControlValueAccessor 和 errorMatcher 的角度材料
- laravel - Laravel 访问仪表板 IF
- r - facet_grid() 的问题,包括不属于 r 分组的变量
- python - ValueError:使用emcee包时概率函数返回NaN
- python - Pandas DataFrame 的整数列中如何存在空格?
- ruby - 红宝石 | 建造金字塔的方法有问题
- reactjs - 如何在“react-google-autocomplete”库中测试地点选项
- statamic - 导航循环中的 from:segment_1 语句提供了错误的结果