1. 程式人生 > >map 如何使用結構體作為自定義鍵值

map 如何使用結構體作為自定義鍵值

在使用map時,有時候我們需要自定義鍵值,才能符合程式的需要。

比如我們需要使用自定義的結構體來作為map的鍵值:

struct  Test
{
    int x;
    int y;
};

這樣直接使用的話,在編譯時會出問題:

1>------ Build started: Project: MapRemove, Configuration: Debug Win32 ------
1>  Source.cpp
1>d:\program files (x86)\microsoft visual studio 12.0\vc\include\xstddef(193
): error C2784: 'bool std::operator <(const std::tuple<_Types...> &,const std::tuple<_Types1...> &)' : could not deduce template argument for 'const std::tuple<_Types...> &' from 'const Test' 1> d:\program files (x86)\microsoft visual studio 12.0\vc\include
\tuple(480) : see declaration of 'std::operator <' 1> d:\program files (x86)\microsoft visual studio 12.0\vc\include\xstddef(192) : while compiling class template member function 'bool std::less<_Kty>::operator ()(const _Ty &,const _Ty &) const' 1> with 1> [ 1>
_Kty=Test 1> , _Ty=Test 1> ] 1> d:\program files (x86)\microsoft visual studio 12.0\vc\include\map(228) : see reference to function template instantiation 'bool std::less<_Kty>::operator ()(const _Ty &,const _Ty &) const' being compiled 1> with 1> [ 1> _Kty=Test 1> , _Ty=Test 1> ] 1> d:\program files (x86)\microsoft visual studio 12.0\vc\include\type_traits(572) : see reference to class template instantiation 'std::less<_Kty>' being compiled 1> with 1> [ 1> _Kty=Test 1> ] 1> d:\program files (x86)\microsoft visual studio 12.0\vc\include\xtree(1023) : see reference to class template instantiation 'std::is_empty<std::less<_Kty>>' being compiled 1> with 1> [ 1> _Kty=Test 1> ] 1> d:\program files (x86)\microsoft visual studio 12.0\vc\include\map(70) : see reference to class template instantiation 'std::_Tree<std::_Tmap_traits<_Kty,_Ty,_Pr,_Alloc,false>>' being compiled 1> with 1> [ 1> _Kty=Test 1> , _Ty=std::string 1> , _Pr=std::less<Test> 1> , _Alloc=std::allocator<std::pair<const Test,std::string>> 1> ] 1> f:\xdd\xaudio2\mapremove\source.cpp(12) : see reference to class template instantiation 'std::map<Test,std::string,std::less<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>' being compiled 1> with 1> [ 1> _Kty=Test 1> , _Ty=std::string 1> ] 1>d:\program files (x86)\microsoft visual studio 12.0\vc\include\xstddef(193): error C2784: 'bool std::operator <(const std::_Tree<_Traits> &,const std::_Tree<_Traits> &)' : could not deduce template argument for 'const std::_Tree<_Traits> &' from 'const Test' 1> d:\program files (x86)\microsoft visual studio 12.0\vc\include\xtree(2259) : see declaration of 'std::operator <' 1>d:\program files (x86)\microsoft visual studio 12.0\vc\include\xstddef(193): error C2784: 'bool std::operator <(const std::basic_string<_Elem,_Traits,_Alloc> &,const _Elem *)' : could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'const Test' 1> d:\program files (x86)\microsoft visual studio 12.0\vc\include\xstring(2545) : see declaration of 'std::operator <' 1>d:\program files (x86)\microsoft visual studio 12.0\vc\include\xstddef(193): error C2784: 'bool std::operator <(const _Elem *,const std::basic_string<_Elem,_Traits,_Alloc> &)' : could not deduce template argument for 'const _Elem *' from 'const Test' 1> d:\program files (x86)\microsoft visual studio 12.0\vc\include\xstring(2535) : see declaration of 'std::operator <' 1>d:\program files (x86)\microsoft visual studio 12.0\vc\include\xstddef(193): error C2784: 'bool std::operator <(const std::basic_string<_Elem,_Traits,_Alloc> &,const std::basic_string<_Elem,_Traits,_Alloc> &)' : could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'const Test' 1> d:\program files (x86)\microsoft visual studio 12.0\vc\include\xstring(2525) : see declaration of 'std::operator <' 1>d:\program files (x86)\microsoft visual studio 12.0\vc\include\xstddef(193): error C2784: 'bool std::operator <(const std::move_iterator<_RanIt> &,const std::move_iterator<_RanIt2> &)' : could not deduce template argument for 'const std::move_iterator<_RanIt> &' from 'const Test' 1> d:\program files (x86)\microsoft visual studio 12.0\vc\include\xutility(1997) : see declaration of 'std::operator <' 1>d:\program files (x86)\microsoft visual studio 12.0\vc\include\xstddef(193): error C2784: 'bool std::operator <(const std::reverse_iterator<_RanIt> &,const std::reverse_iterator<_RanIt2> &)' : could not deduce template argument for 'const std::reverse_iterator<_RanIt> &' from 'const Test' 1> d:\program files (x86)\microsoft visual studio 12.0\vc\include\xutility(1155) : see declaration of 'std::operator <' 1>d:\program files (x86)\microsoft visual studio 12.0\vc\include\xstddef(193): error C2784: 'bool std::operator <(const std::_Revranit<_RanIt,_Base> &,const std::_Revranit<_RanIt2,_Base2> &)' : could not deduce template argument for 'const std::_Revranit<_RanIt,_Base> &' from 'const Test' 1> d:\program files (x86)\microsoft visual studio 12.0\vc\include\xutility(971) : see declaration of 'std::operator <' 1>d:\program files (x86)\microsoft visual studio 12.0\vc\include\xstddef(193): error C2784: 'bool std::operator <(const std::pair<_Ty1,_Ty2> &,const std::pair<_Ty1,_Ty2> &)' : could not deduce template argument for 'const std::pair<_Ty1,_Ty2> &' from 'const Test' 1> d:\program files (x86)\microsoft visual studio 12.0\vc\include\utility(230) : see declaration of 'std::operator <' 1>d:\program files (x86)\microsoft visual studio 12.0\vc\include\xstddef(193): error C2676: binary '<' : 'const Test' does not define this operator or a conversion to a type acceptable to the predefined operator ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

看錯誤是說,鍵值無法比較。因為map的鍵值是自動比較後進插入的,鍵值是遞增的。

現在我們自定義的鍵值,編譯器無法進行比較,找不到類似的模板,所以報錯。

既然是沒有‘<’,那我們自己過載小於操作符應該就可以了:

struct  Test
{
    int x;
    int y;

    bool operator < (const Test &o) const
    {
        return x < o.x || y < o.y;
    }
};

過載後,重新編譯,順利通過。測試程式碼如下:

#include <map>
#include <iostream>

struct  Test
{
    int x;
    int y;

    bool operator < (const Test &o) const
    {
        return x < o.x || y < o.y;
    }
};

int main()
{
    std::map<Test, std::string> mapTest;
    Test test = { 1, 2 };
    mapTest[test] = "Test1";

    for (auto it = mapTest.begin(); it != mapTest.end();it++)
    {
        std::cout << it->first.x << " " << it->first.y << " " << it->second.c_str() << std::endl;
    }

    return 0;
}

測試結果:

1 2 Test1