大家好我正在从一个主要在MSVS中开发的项目中移植一些代码以使用g++。我发现很多细微的差别,大部分是MSVS允许的,而g++不允许。通常,它涉及c++标准,MSVS可以让它们滑动,但是我很难看到一个特定部分到底出了什么问题。

g++在匹配对运算符!=的调用时遇到了麻烦,但仅在特定情况下才是如此。如果宿主类不是模板,则可以为特定的嵌套类查找运算符!=。但是,如果我将托管类转换为类模板,那么一切都会中断。我或者缺少了c++的基础知识,或者g++做错了什么。

我学会了不要哭“编译器错误!”。太频繁了,所以我想看看这里是否有人可以看到我所缺少的东西。

这个工作示例显示了正常的非模板版本,然后显示了损坏的模板版本。
g++ --version提供:g++(Ubuntu 4.4.1-4ubuntu9)4.4.1

不带模板的工作引用版本

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

带有模板的残破版本
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

模板版本因以下错误而失败:
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]()’

最佳答案

这不适用于msvc和gcc。

问题在于,在host<T>::iterator中,T在不可推论的上下文中。由于两个参数都不允许推导T,因此无法实例化功能模板。

这就是为什么您通常在类内部定义重载运算符。

struct iterator
{
    friend bool operator != (iterator const & lhs, iterator const & rhs)
    {
        return false;
    }
};

09-25 21:01