在msvs中工作的另一个东西的g ++编译错误

时间:2010-02-01 21:45:19

标签: c++ g++

Heya,伙计们。我正在从一个主要在MSVS中开发的项目中移植一些代码来使用g ++。我发现了很多小的差异,主要是MSVS允许的东西,但g ++没有。通常它涉及c ++标准,MSVS允许滑动的东西,但我很难看到一个特定部分出了什么问题。

g ++在调用operator!=时遇到问题,但仅限于特定的上下文。如果托管类不是模板,则查找operator!=对于特定的嵌套类。但是,如果我将托管类转换为类模板,则一切都会中断。我要么缺少c ++的基本功能,要么g ++做错了。

我学会了不要哭“Compiler Bug!”太常见了,所以我想看看这里是否有人能看到我所缺少的东西。

此工作示例显示了工作的非模板版本,然后是损坏的模板版本。 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]()’

3 个答案:

答案 0 :(得分:5)

这既不适用于msvc也不适用于gcc。

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

这就是你经常在类中定义重载运算符的原因。

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

答案 1 :(得分:0)

我打了类似的东西。 C ++运算符重载应该采用const输入。 msvc可以让你使用非常量输入。 G ++坚持认为它们是const

答案 2 :(得分:0)

建立一个@ 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

这解决了以下问题:顶层operator !=的模板参数无法通过使用友元函数中的显式模板参数调用来推断。它需要转发声明host模板。