我想在命令start和end函数模板中使用一个带有成员变量的简单结构:
#include <iostream>
using namespace std;
struct st {
int start;
int end;
};
template<typename T>
void compare(const T& v1, const T& v2){
if(v1.end < v2.end)
cout << "v1 < v2" << endl;
}
int main() {
st a = {1, 2};
st b = {2, 3};
compare(a, b);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是这个程序无法在mingw g ++ 4.8.2上编译:
main.cpp: In function 'void compare(const T&, const T&)':
main.cpp:11:11: error: parse error in template argument list
if(v1.end < v2.end)
^
main.cpp: In instantiation of 'void compare(const T&, const T&) [with T = st]':
main.cpp:18:17: required from here
main.cpp:11:5: error: 'end' is not a member template function
if(v1.end < v2.end)
^
Run Code Online (Sandbox Code Playgroud)
为什么不?我的代码出了什么问题?
这显然是一个gcc bug(特别是10200,尽管有几个dupes有很多不同的例子).[temp.names]声明:
当成员模板专业化的名称出现之后.或-在一个> 后缀表达式或一后 嵌套名称说明符在一个合格-ID,和对象表达后缀表达式是类型相关 或嵌套名称说明符在合格-ID是指,以一个依赖类型,但名称不是当前实例化的成员(14.6.2.1),成员模板名称必须以关键字为前缀
template. 否则,假定该名称命名非模板. [例如:Run Code Online (Sandbox Code Playgroud)struct X { template<std::size_t> X* alloc(); template<std::size_t> static X* adjust(); }; template<class T> void f(T* p) { T* p1 = p->alloc<200>(); // ill-formed: < means less than T* p2 = p->template alloc<200>(); // OK: < starts template argument list T::adjust<100>(); // ill-formed: < means less than T::template adjust<100>(); // OK: < starts template argument list }- 末端的例子]
v1并且v2是类型相关的,因此应该假定名称由于省略的template关键字而命名非模板,并且<应该将其视为小于,与上面的示例完全相同.
更不用说[basic.lookup.classref]声明:
首先在对象表达式的类中查找标识符.如果未找到标识符,则在整个postfix-expression的上下文中查找它,并命名一个类模板.
并且end应该清楚地在对象表达式的类中找到 - 毕竟它是一个简单的成员变量.它end只是因为碰撞而失败的事实std::end()进一步支持了bug的想法,因为该范围永远不应该被认为是开始的.
有趣的是,最简单的解决方案就是:不要使用using namespace std;!
实际上,它<会混淆编译器,因为它不知道它是模板表达式的开始还是比较器.
由于@R Sahu要求官方消息来源,以下是解释:
这里重要的段落是[basic.lookup.classref] p1:
"在类成员访问表达式(5.2.5)中,如果
.或者->后面跟着一个标识符后面跟着一个<,则必须查找标识符以确定<是否是模板参数列表的开头(14.2)首先在对象表达式的类中查找标识符.如果没有找到标识符,则在整个postfix-expression的上下文中查找它,并命名一个类模板."或者一个小于运算符.由于v是依赖的,可能是找不到标识符所以我们考虑如果我们查看整个postfix-expression的上下文会发生什么.由于我们找到了一个函数模板,因此我们不应该断定我们有一个模板ID的开头.
这是相应的gcc错误:https://gcc.gnu.org/bugzilla/show_bug.cgi?id = 010200
*Paolo Carlini 2015-06-23 15:03:03 UTC*
错误65878已被标记为此错误的副本.
*Colin MacKenzie 2015-06-23 22:19:29 UTC*
今天有这个.奇怪的是它在4.4.6中编译得很好但在4.8.2中没编译.
error: parse error in template argument list
Ex: assert(block.begin < block.end);
works when I parenthesize the block.begin
Ex. assert( (block.begin) < block.end);
Run Code Online (Sandbox Code Playgroud)
*Paolo Carlini 2015-06-23 22:21:28 UTC*
这应该尽快修复,但我现在还没有积极地处理它.
| 归档时间: |
|
| 查看次数: |
325 次 |
| 最近记录: |