[英]g++ compilation error of another thing that works in msvs
Heya, folks. 大家好 I'm porting some code from a project largely developed in MSVS to use g++. 我正在从一个主要在MSVS中开发的项目中移植一些代码以使用g ++。 I've found a lot of little differences, mostly things that MSVS allows but g++ does not. 我发现很多细微的差别,大部分是MSVS允许的,而g ++不允许。 Usually it's something involving c++ standards, things that MSVS lets slide, but I'm having trouble seeing just what's wrong with one particular section. 通常,它涉及c ++标准,MSVS可以让它们滑动,但是我很难看到一个特定部分到底出了什么问题。
g++ is having trouble matching a call to operator !=, but only in a specific context. g ++在匹配对运算符!=的调用时遇到麻烦,但仅在特定情况下才可以。 Looking up operator != for a particular nested class works if the hosting class is not a template. 如果宿主类不是模板,则查找特定嵌套类的运算符!=即可。 If I turn the hosting class into a class template, however, everything breaks. 但是,如果我将托管类转换为类模板,则一切都会中断。 I'm either missing something fundamental to c++, or g++ is doing something wrong. 我或者缺少了c ++的基础知识,或者g ++做错了什么。
I've learned not to cry "Compiler Bug!" 我学会了不要哭“编译器错误!”。 too often, so I wanted to see if anyone here can see what I'm missing. 太频繁了,所以我想看看这里是否有人可以看到我所缺少的东西。
This worked example shows the working, non-template version, and then the broken, template version. 此工作示例显示了有效的非模板版本,然后显示了损坏的模板版本。 g++ --version gives: g++ (Ubuntu 4.4.1-4ubuntu9) 4.4.1 g ++ --version提供:g ++(Ubuntu 4.4.1-4ubuntu9)4.4.1
Working reference version without templates 没有模板的工作参考版本
namespace Works {
struct host {
struct iterator {};
iterator op();
};
bool operator != (host::iterator const& a0, host::iterator const& a1);
bool f() {
return host().op() != host().op();
}
} // namespace Works
Broken version with templates 模板版本破损
namespace Broken {
template <typename T>
struct host {
struct iterator {};
iterator op();
};
template <typename T>
bool operator != (typename host<T>::iterator const& a0,
typename host<T>::iterator const& a1);
bool f() {
return host<int>().op() != host<int>().op();
}
} // namespace Broken
The template version fails with the errors: 模板版本因以下错误而失败:
Main.cpp: In function ‘bool Broken::f()’:
Main.cpp:50: error: no match for ‘operator!=’ in ‘Broken::host<int>().Broken::host<T>::op [with T = int]() != Broken::host<int>().Broken::host<T>::op [with T = int]()’
This works neither in msvc nor gcc. 这不适用于msvc和gcc。
The problem is that in host<T>::iterator
, T
is in non-deducible context. 问题是在host<T>::iterator
, T
在不可推论的上下文中。 Since neither parameter allows T
to be deduced, the function template cannot be instantiated. 由于两个参数都不允许推导T
,因此无法实例化功能模板。
That's why you usually define overloaded operators inside the class. 这就是为什么通常在类中定义重载运算符。
struct iterator
{
friend bool operator != (iterator const & lhs, iterator const & rhs)
{
return false;
}
};
i hit a similar thing. 我打了类似的事情。 C++ operator overloads are supposed to take const inputs. C ++运算符重载应该采用const输入。 msvc will let you get away with using non const inputs. msvc将使您摆脱使用非const输入的麻烦。 G++ insists they are const G ++坚持认为它们是const
Building an @avakar's answer, I got the code to work properly, though it's a little strange: 构建一个@avakar的答案,尽管有些奇怪,但我的代码可以正常工作:
namespace Broken {
template <typename T> struct host;
template <typename T>
bool operator != (typename host<T>::iterator const& a0,
typename host<T>::iterator const& a1);
template <typename T>
struct host {
struct iterator {
friend bool operator !=(iterator const & lhs, iterator const & rhs) {
return operator !=<int>(lhs, rhs);
}
};
iterator op();
};
bool f() {
// The following does indeed end up calling the operator != you want it to call. I
// have a slightly different version in which I tested this.
return host<int>().op() != host<int>().op();
}
} // namespace Broken
This gets around the problem that the template arguments to the top level operator !=
cannot be deduced by calling it with an explicit template argument from a friend function. 这就解决了以下问题:顶级operator !=
的模板参数无法通过使用好友函数中的显式模板参数进行调用来推导。 It requires forward declaring the host
template. 它需要向前声明host
模板。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.