为什么 VS2015 中模板相关的嵌套类型名称不需要 typename 关键字?
Why typename keyword is not needed in template dependent nested type names in VS2015?
我正在阅读有关 typename
在 C++ 模板编程中的用法(例如 this Q/A). To me, it seems that when using a dependent nested type name, we should use typename
for avoiding parsing ambiguity. I also checked this on Scot Meyers book effective C++,项目 #42。
但令我感到奇怪的是,书中的相同示例在没有 typename
的情况下仍然有效。这是代码:
template<class C>
void Print2nd(const C & cont)
{
if (cont.size() >= 2)
{
C::const_iterator * iter1 = new C::const_iterator(cont.begin()); // why typename is NOT needed?
C::const_iterator iter2 = cont.begin(); // why typename is NOT needed?
(*iter1)++;
iter2++;
int value1 = **iter1;
int value2 = *iter2;
std::cout << "The value of 2nd with pointer is: " << value1 << std::endl;
std::cout << "The value of 2nd without pointer is: " << value2 << std::endl;
}
}
int main()
{
std::vector<int> vect = {1,2,3,4,5,6};
Print2nd(vect);
return 0;
}
我正在使用 VS2015。那么,问题是为什么在这种情况下不需要 typename
?最近的 C++ 编译器是否有任何升级以避免在这种情况下使用 typename
?还是我的代码有误?
更新 1: 感谢@FrançoisAndrieux 的评论,似乎在 VS2008 和 VS2010 中发生了同样的事情,如 this Q/A 中所报告的。
typename
需要;示例程序格式错误。如果编译器没有诊断出问题,那么它就不符合标准。正确的版本是:
typename C::const_iterator * iter1 = new typename C::const_iterator(cont.begin());
// ^^^^^^^^ this one only required until C++20
typename C::const_iterator iter2 = cont.begin();
标准引用(C++17 草案):
[temp.res]
A name used in a template declaration or definition and that is dependent on atemplate-parameteris assumednot to name a type unless the applicable name lookup finds a type name or the name is qualified by the keyword typename
.
C::const_iterator
取决于模板参数 C
,因此除非使用 typename
,否则不应将其假定为类型名称。我认为该语句应解释为乘法运算,但右侧操作数是未声明的标识符,因此格式错误。
C++20 引入了允许从新表达式(最新草案)中删除 typename
的规则:
[temp.res]
A qualified name is said to be in a type-id-only context if it appears in a type-id, new-type-id, or defining-type-id and the smallest enclosing type-id, new-type-id, or defining-type-id is a new-type-id, defining-type-id, trailing-return-type, default argument of a type-parameter of a template, or type-id of a static_cast, const_cast, reinterpret_cast, or dynamic_cast.
您可能想创建一个类型别名以提高可读性:
using const_iterator = typename C::const_iterator;
或者您可以只使用 auto
:
auto it = cont.begin();
P.S。动态分配迭代器几乎没有意义。
In c++20 那里不需要 typename
。在某些情况下,删除了 typename
的需要,因为从句法上讲 必须 是一个类型。
特别是:
A qualified name that appears in type-id, where the smallest enclosing type-id is:
- the type in a new expression that does not parenthesize its type;
Quoted source 并非直接来自标准,但相当可靠。
在 c++20 之前 typename
是需要的;它将被解析为一个值,并且 new value
不是有效语法。在 c++20 中,typename
在该上下文中是 可选的 。
现在,visual-studio-2015 中没有 c++20 功能;你看到的是 MSVC 未能正确实现 c++11/c++14/c++17 ,不是 c++20 扩展名。
我正在阅读有关 typename
在 C++ 模板编程中的用法(例如 this Q/A). To me, it seems that when using a dependent nested type name, we should use typename
for avoiding parsing ambiguity. I also checked this on Scot Meyers book effective C++,项目 #42。
但令我感到奇怪的是,书中的相同示例在没有 typename
的情况下仍然有效。这是代码:
template<class C>
void Print2nd(const C & cont)
{
if (cont.size() >= 2)
{
C::const_iterator * iter1 = new C::const_iterator(cont.begin()); // why typename is NOT needed?
C::const_iterator iter2 = cont.begin(); // why typename is NOT needed?
(*iter1)++;
iter2++;
int value1 = **iter1;
int value2 = *iter2;
std::cout << "The value of 2nd with pointer is: " << value1 << std::endl;
std::cout << "The value of 2nd without pointer is: " << value2 << std::endl;
}
}
int main()
{
std::vector<int> vect = {1,2,3,4,5,6};
Print2nd(vect);
return 0;
}
我正在使用 VS2015。那么,问题是为什么在这种情况下不需要 typename
?最近的 C++ 编译器是否有任何升级以避免在这种情况下使用 typename
?还是我的代码有误?
更新 1: 感谢@FrançoisAndrieux 的评论,似乎在 VS2008 和 VS2010 中发生了同样的事情,如 this Q/A 中所报告的。
typename
需要;示例程序格式错误。如果编译器没有诊断出问题,那么它就不符合标准。正确的版本是:
typename C::const_iterator * iter1 = new typename C::const_iterator(cont.begin());
// ^^^^^^^^ this one only required until C++20
typename C::const_iterator iter2 = cont.begin();
标准引用(C++17 草案):
[temp.res]
A name used in a template declaration or definition and that is dependent on atemplate-parameteris assumednot to name a type unless the applicable name lookup finds a type name or the name is qualified by the keyword
typename
.
C::const_iterator
取决于模板参数 C
,因此除非使用 typename
,否则不应将其假定为类型名称。我认为该语句应解释为乘法运算,但右侧操作数是未声明的标识符,因此格式错误。
C++20 引入了允许从新表达式(最新草案)中删除 typename
的规则:
[temp.res]
A qualified name is said to be in a type-id-only context if it appears in a type-id, new-type-id, or defining-type-id and the smallest enclosing type-id, new-type-id, or defining-type-id is a new-type-id, defining-type-id, trailing-return-type, default argument of a type-parameter of a template, or type-id of a static_cast, const_cast, reinterpret_cast, or dynamic_cast.
您可能想创建一个类型别名以提高可读性:
using const_iterator = typename C::const_iterator;
或者您可以只使用 auto
:
auto it = cont.begin();
P.S。动态分配迭代器几乎没有意义。
In c++20 那里不需要 typename
。在某些情况下,删除了 typename
的需要,因为从句法上讲 必须 是一个类型。
特别是:
A qualified name that appears in type-id, where the smallest enclosing type-id is:
- the type in a new expression that does not parenthesize its type;
Quoted source 并非直接来自标准,但相当可靠。
在 c++20 之前 typename
是需要的;它将被解析为一个值,并且 new value
不是有效语法。在 c++20 中,typename
在该上下文中是 可选的 。
现在,visual-studio-2015 中没有 c++20 功能;你看到的是 MSVC 未能正确实现 c++11/c++14/c++17 ,不是 c++20 扩展名。