
在 C++ 模板编程中,尖括号 < 和 > 用于指定模板参数。当模板嵌套使用时,例如 vector<list<int>>,编译器需要正确解析连续的两个 > 符号——它究竟是模板参数列表的结束符,还是右移运算符 >>?
C++98/03 时代的规则:必须添加空格
在 C++98 和 C++03 标准中,词法分析器会将 >> 始终解释为右移运算符(或流提取运算符)。因此,写下 vector<list<int>> 会被解析为 (vector<list<int>) > 或者产生一个语法错误,因为 >> 被当作一个单独的记号,而不是两个独立的 >。
解决方法:在两个 > 之间插入一个空格,写成 > >,强制编译器将它们视为两个独立的结束符。
// C++98 / C++03 合法写法
#include<vector>
#include<list>
intmain(){
std::vector<std::list<int> > vl; // 注意 > > 之间的空格
// std::vector<std::list<int>> vl; // 错误!>> 被当作右移运算符
return0;
}
C++11 及之后的改进:放宽规则
C++11 标准对模板语法进行了精细化调整,规定在模板参数列表结束的上下文中,连续的 >> 会被正确解析为两个右尖括号,而不再与右移运算符混淆。这使得代码书写更自然、更符合直觉。
// C++11 及之后合法写法
#include<vector>
#include<list>
intmain(){
std::vector<std::list<int>> vl; // 现在可以直接使用 >>
// 完全等价于旧式的 std::vector<std::list<int> > vl;
return0;
}
注意事项
向后兼容:C++11 之后的编译器仍然接受带空格的 > >写法,旧代码可以继续编译。右移运算符歧义消除:编译器会根据上下文判断 >>的含义。如果>>出现在模板参数列表的结束位置,它会被解释为两个右尖括号;否则仍为右移运算符。C++14/17/20:这一规则保持有效,且嵌套更深的模板(如 vector<map<string, vector<int>>>)也能正确解析。
完整对比示例
#include<iostream>
#include<vector>
#include<list>
#include<map>
// 一个简单的模板类,用于演示
template<typename T>
structWrapper {
T value;
};
intmain(){
// ---------- C++98/03 风格 ----------
std::vector<std::list<int> > old_style; // 需要空格
Wrapper<std::vector<int> > old_wrapper; // 需要空格
// ---------- C++11 及之后风格 ----------
std::vector<std::list<int>> new_style; // 直接使用 >>
Wrapper<std::vector<int>> new_wrapper; // 更清晰
std::map<std::string, std::vector<int>> map_of_vectors; // 常见用法
// 嵌套三层也正确
std::vector<std::map<std::string, std::vector<int>>> complex;
std::cout << "C++11 之后,嵌套模板的 >> 写法完全合法!\n";
return0;
}
编译验证
使用 -std=c++98或-std=c++03编译含有>>(无空格)的代码会报错。使用 -std=c++11或更高标准编译,上述代码全部通过。
因此,如果你的项目允许使用 C++11 或更新标准,建议直接采用简洁的 >> 写法;如果仍需兼容古老编译器,请保留空格。
夜雨聆风