Search code examples
c++stlstdmapboost-tuples

Issue with key of std::map


Consider the following code. A tuple consisting of integer and vector of integer is defined as the key of a map. However, I was surprised that the compiler does not throw any error when inserting or looking for a tuple consisting of integer and integer as the key. How can this be, since the second element of the tuple should be of the type vector of integer?

std::map <boost::tuple<int, vector<int > >, int> test;
std::map <boost::tuple<int, vector<int > >, int>::iterator test_it;

vector <int> t;
t.push_back(4);

test.insert(make_pair(boost::make_tuple(3, t), 4));

test.insert(make_pair(boost::make_tuple(3, 6), 4));

test_it = test.find(boost::make_tuple(3, 7)); 
if(test_it != test.end()) 
throw " test is passed";  

Solution

  • Seems like a bug in Boost and many C++ standard library implementations. The problem is shared by both pair and tuple. The simplest code to demonstrate it is:

    #include <vector>
    #include <utility>
    using namespace std;
    int main() {
        //compiles
        pair<int,vector<int>> bug1( pair<int,int>(5,6) );
    
        //compiles
        pair<int,vector<int>> bug2;
        bug2 = pair<int,int>(5,6);
    }
    

    Clang 4.0 with libc++ and the other one accepts this, Comeau Online accepts it too. GCC 4.7.1 gives an error.

    It must not compile, according to:

    20.3.2/12

    template<class U, class V> pair(const pair<U, V>& p);
    

    Remark: This constructor shall not participate in overload resolution unless const U& is implicitly convertible to first_type and const V& is implicitly convertible to second_type.

    20.3.2/23

    template<class U, class V> pair& operator=(const pair<U, V>& p);
    

    Requires: is_assignable<first_type&, const U&>::value is true and is_assignable<second_type&, const V&>::value is true.