繁体   English   中英

g ++编译错误在msvs中有效的另一件事

[英]g++ compilation error of another thing that works in msvs

大家好 我正在从一个主要在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>::iteratorT在不可推论的上下文中。 由于两个参数都不允许推导T ,因此无法实例化功能模板。

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

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

我打了类似的事情。 C ++运算符重载应该采用const输入。 msvc将使您摆脱使用非const输入的麻烦。 G ++坚持认为它们是const

构建一个@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模板。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM