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";
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
istrue
andis_assignable<second_type&, const V&>::value
istrue
.