为什么"不匹配'运营商<'"当我宣布它?

时间:2016-04-09 05:08:50

标签: c++ templates stl namespaces operator-overloading

适用于我声明的struct xy。为什么complex<int>的相同模式不起作用?

#include <complex>
#include <set>
using namespace std;

struct xy {
    int x, y;
};

bool operator< (const xy &a, const xy &b) {
    return a.x < b.x;
}

bool operator< (const complex<int> &a, const complex<int> &b) {
    return a.real() < b.real();
}

int main() {
    xy q;
    set<xy> s;
    s.insert(q);

    complex<int> p;
    set< complex<int> > t;   //If I comment out these two lines,
    t.insert(p);             //it compiles fine.

    return 0;
}

错误消息:

In file included from c:\m\lib\gcc\mingw32\4.8.1\include\c++\string:48:0,
                 from c:\m\lib\gcc\mingw32\4.8.1\include\c++\bits\locale_classes.h:40,
                 from c:\m\lib\gcc\mingw32\4.8.1\include\c++\bits\ios_base.h:41,
                 from c:\m\lib\gcc\mingw32\4.8.1\include\c++\ios:42,
                 from c:\m\lib\gcc\mingw32\4.8.1\include\c++\istream:38,
                 from c:\m\lib\gcc\mingw32\4.8.1\include\c++\sstream:38,
                 from c:\m\lib\gcc\mingw32\4.8.1\include\c++\complex:45,
                 from test.cpp:1:
c:\m\lib\gcc\mingw32\4.8.1\include\c++\bits\stl_function.h: In instantiation of 'bool less<>::operator()(const _Tp&, const _Tp&) const':
c:\m\lib\gcc\mingw32\4.8.1\include\c++\bits\stl_tree.h:1321:11:   required from 'pair<> _Rb_tree<>::_M_get_insert_unique_pos(const key_type&)'
c:\m\lib\gcc\mingw32\4.8.1\include\c++\bits\stl_tree.h:1374:47:   required from 'pair<> _Rb_tree<>::_M_insert_unique(_Arg&&)'
c:\m\lib\gcc\mingw32\4.8.1\include\c++\bits\stl_set.h:463:29:   required from 'pair<> __cxx1998::set<>::insert(const value_type&)'
c:\m\lib\gcc\mingw32\4.8.1\include\c++\debug\set.h:220:59:   required from 'pair<> __debug::set<>::insert(const value_type&)'
test.cpp:28:19:   required from here
c:\m\lib\gcc\mingw32\4.8.1\include\c++\bits\stl_function.h:235:20: 
error: no match for 'operator<' (operand types are 'const std::complex<int>' and 'const std::complex<int>')
       { return __x < __y; }

我最好的猜测是,这与complex<T>是一个类,而不是一个结构有关。我无法理解为什么这应该有所作为的逻辑。或者它是一些模板可怕吗?

我看到的是,STL在某些时候尝试(粗略地说)做a < b,其中abcomplex<int>个实例。所以它正在寻找bool operator< (const complex<int> &a, const complex<int> &b)。好吧,正好在main()之上宣布了。为什么这是不合理的?我想也许它不喜欢它们被引用。但删除&符号对其投诉没有任何影响。

3 个答案:

答案 0 :(得分:2)

一种选择是编写自定义比较函子,并用此实例化该集。

#include <complex>
#include <set>    

bool operator< (const std::complex<int> &a, const std::complex<int> &b) {
    return a.real() < b.real();
}

struct my_less {
    bool operator() (const std::complex<int>& lhs, const std::complex<int>& rhs) const{
        return lhs < rhs;
    }
};

int main() {
    std::complex<int> p;
    std::set< std::complex<int>, my_less > t;
    t.insert(p);

    return 0;
}

Sample on Coliru

答案 1 :(得分:2)

  

适用于我声明的struct xy。为什么相同的模式不适用于complex<int>

原因是当你只使用来自命名空间std的类型时,如std::setstd::complex,编译器没有理由在任何其他命名空间中查找运算符。

对于struct xy,这是不同的,因为运算符与类型一起声明。

而且,目前的标准说:

  

为float,double或long double以外的任何类型实例化模板复合体的效果是   未指定的。

因此,根据您使用的编译器,使用complex<int>可能会或可能不会。 “未指定”并不像“未定义”那么糟糕,但是 当然不是很可靠或便携。

答案 2 :(得分:0)

从今天开始,我的Ubuntu g ++面临这个问题。假设我有:

namespace X { namespace Y { class C { ... }; } }

现在operator==如果在全局名称空间中定义,则可以识别,例如:

bool operator== (const X::Y::C& lhs, const X::Y::C& rhs) { return lhs == rhs; }

但是,如果以相同的方式定义,编译器将无法识别operator<

现在,以下方法效果很好:

namespace X { namespace Y { 
     bool operator< (const C& lhs, const C& rhs) { return lhs < rhs; } } }

但是,是否应该对扩展标准namespace std进行相同操作是一个有争议的话题。 :-)