2012-02-04 24 views
6

クラス階層にオブジェクトがたくさんあり、そのオブジェクトへの参照をマップのキーとして使用してstd::mapにしたいと考えています。そのためにはstd::reference_wrapperのように思えるが、これは必要なものだが、私はそれを機能させることができない。私がこれまで試した:std :: mapのstd :: reference_wrapperをキーとして使用する

class Object { // base class of my hierarchy 
    // most details unimportant 
public 
    virtual bool operator< (const Object &) const; // comparison operator 
}; 

std::map<std::reference_wrapper<const Object>, int> table; 

auto it = table.find(object); 

table[object] = 42; 

table[object]++ 

しかし、私はいつも、コンパイラからややあいまいなエラーを取得:

/usr/include/c++/4.5.3/bits/stl_function.h: In member function ‘bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = std::reference_wrapper<const Object>]’: 
/usr/include/c++/4.5.3/bits/stl_tree.h:1522:38: instantiated from ‘std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::find(const _Key&) [with _Key = std::reference_wrapper<const Object>, _Val = std::pair<const std::reference_wrapper<const Object>, int>, _KeyOfValue = std::_Select1st<std::pair<const std::reference_wrapper<const Object>, int> >, _Compare = std::less<std::reference_wrapper<const Object> >, _Alloc = std::allocator<std::pair<const std::reference_wrapper<const Object>, int> >, std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const std::reference_wrapper<const Object>, int> >]’ 
/usr/include/c++/4.5.3/bits/stl_map.h:697:29: instantiated from ‘std::map<_Key, _Tp, _Compare, _Alloc>::iterator std::map<_Key, _Tp, _Compare, _Alloc>::find(const key_type&)[with _Key = std::reference_wrapper<const Object>, _Tp = int, _Compare = std::less<std::reference_wrapper<const Object> >, _Alloc = std::allocator<std::pair<const std::reference_wrapper<const Object>, int> >, std::map<_Key, _Tp, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const std::reference_wrapper<const Object>, int> >, key_type = std::reference_wrapper<const Object>]’ 
testfile.cpp:39:31: instantiated from here 
/include/c++/4.5.3/bits/stl_function.h:230:22: error: no match for ‘operator<’ in ‘__x < __y’ 

エラーは、2つのstd::reference_wrapper<const Object>のオブジェクトを比較することはできませんと言っているように見えるが、可能であれば、std::reference_wrapperに暗黙的にT&const Object &)に変換できる変換演算子があり、Objectにはoperator <が含まれていますが、なぜ機能しないのですか?

これはうまくいきますか?これはg ++のバグにすぎませんか?それとも別のことが起こっていますか?

+0

'std :: ref(オブジェクト) dalle

答えて

5

比較演算子を(おそらく仮想メンバ関数を呼び出す)フリー関数にした場合はうまくいくようです。

メンバー関数の場合、a < bは実際にはa.operator<(b);を意味し、暗黙的な変換は左側の引数には考慮されません。

1

Visual Studio 11 Betaでは、同じ問題が発生します。 <オペレータを呼び出す無料版を使用すると問題が解決します。デフォルトstd::less<std::reference_wrapper<const Object>>ことで

#include<map> 
#include<iostream> 
using namespace::std; 

class Object { 
    int _n1; 
public: 

    Object(int n = 0):_n1(n){}; 
    bool operator < (const Object& rhs) const {return this->_n1 < rhs._n1;} 
    friend ostream &operator << (ostream &stream, const Object& o) { stream << o._n1 << " "; return stream;} 
}; 

struct ObjectLess{ 

    bool operator()(const Object& lhs, const Object& rhs) const 
    { 
     return lhs<rhs; 
    } 
}; 

int main(int argc, char* argv[]) 
{ 
    //This does not compile 
    //std::map<std::reference_wrapper<const Object>, string> table; 

    //Using the free function works 
    std::map<std::reference_wrapper<const Object>, string, ObjectLess> table; 

    Object a(1); 
    Object b(2); 
    Object c(3); 


    table[a]="One"; 
    table[c]="Three"; 
    table[b]="Two"; 

    for(auto y: table){ 
    cout << y.first << " " << y.second.c_str() << std::endl; 
} 


    return 0; 
} 
3

使用されているが、それは基本的な型にoperator<()を転送しません。

あなたの問題を解決するための最も簡単なとconcisestオプションは、このようなマップ定義でstd::less<const Object>(またはstd::greater<const Object>)を定義することです:

std::map<std::reference_wrapper<const Object>, int, std::less<const Object>> table; 

それが正常に動作し、原因implicit conversion of std::reference_wrapper to T&implicit constructor of std::reference_wrapperに期待されるようになります。

Example

関連する問題