I have created a non-copyable map which I cannot get to compile with clang. Since clang is meant to be very standards compliant I was wondering if my code was legal. MSVS 2010 and GCC 4.7 compile this code without warnings or errors.
Full code is attached: the problematic line is the last line of main
.
= delete
needs removing for MSVS 2010
#include <utility>
#include <iostream>
#include <map>
template<typename Key_t, typename Value_t, typename Compare_t = std::less<Key_t> >
class non_copyable_map : public std::map<Key_t,Value_t,Compare_t>
{
typedef std::map<Key_t,Value_t,Compare_t> BaseType;
public:
non_copyable_map() { }
non_copyable_map(non_copyable_map&& t) : BaseType(std::move(t)) {}
non_copyable_map& operator = (non_copyable_map&& t)
{
if ( this != &t )
{
std::swap<BaseType>(*this,t);
}
return *this;
}
private:
non_copyable_map(const non_copyable_map&) = delete;
non_copyable_map& operator = (const non_copyable_map&) = delete;
};
int main(int argc, char* argv[])
{
non_copyable_map<int, non_copyable_map<int, int> > nestedMap;
non_copyable_map<int,int> inner;
inner[3]=4;
nestedMap[2] = std::move(inner); // THIS LINE CAUSES CLANG PROBLEMS
}
Error message when using clang++-mp-3.1 -std=c++0x -stdlib=libc++ MapOfMaps.cpp
is:
In file included from MapOfMaps.cpp:2:
In file included from /usr/include/c++/v1/iostream:40:
In file included from /usr/include/c++/v1/istream:156:
In file included from /usr/include/c++/v1/ostream:134:
In file included from /usr/include/c++/v1/bitset:118:
/usr/include/c++/v1/__bit_reference:26:26: error: no type named '__storage_type' in
'std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<const
int, int> > >'
typedef typename _C::__storage_type __storage_type;
~~~~~~~~~~~~~^~~~~~~~~~~~~~
MapOfMaps.cpp:21:25: note: in instantiation of template class
'std::__1::__bit_reference<std::__1::map<int, int, std::__1::less<int>,
std::__1::allocator<std::__1::pair<const int, int> > > >' requested here
std::swap<BaseType>(*this,t);
^
MapOfMaps.cpp:36:15: note: in instantiation of member function 'non_copyable_map<int, int,
std::__1::less<int> >::operator=' requested here
nestedMap[2] = std::move(inner);
^
In file included from MapOfMaps.cpp:2:
In file included from /usr/include/c++/v1/iostream:40:
In file included from /usr/include/c++/v1/istream:156:
In file included from /usr/include/c++/v1/ostream:134:
In file included from /usr/include/c++/v1/bitset:118:
/usr/include/c++/v1/__bit_reference:27:26: error: no type named '__storage_pointer' in
'std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<const
int, int> > >'
typedef typename _C::__storage_pointer __storage_pointer;
~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~
/usr/include/c++/v1/__bit_reference:33:25: error: no type named '__self' in
'std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<const
int, int> > >'
friend typename _C::__self;
~~~~~~~~~~~~~^~~~~~
In file included from MapOfMaps.cpp:3:
In file included from /usr/include/c++/v1/map:338:
/usr/include/c++/v1/__tree:1291:14: error: overload resolution selected deleted operator '='
__pair3_ = _STD::move(__t.__pair3_);
~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/v1/__tree:1308:9: note: in instantiation of member function
'std::__1::__tree<std::__1::pair<int, int>, std::__1::__map_value_compare<int, int,
std::__1::less<int>, true>, std::__1::allocator<std::__1::pair<int, int> >
>::__move_assign' requested here
__move_assign(__t, true_type());
^
/usr/include/c++/v1/__tree:1353:5: note: in instantiation of member function
'std::__1::__tree<std::__1::pair<int, int>, std::__1::__map_value_compare<int, int,
std::__1::less<int>, true>, std::__1::allocator<std::__1::pair<int, int> >
>::__move_assign' requested here
__move_assign(__t, integral_constant<bool,
^
/usr/include/c++/v1/map:736:21: note: in instantiation of member function
'std::__1::__tree<std::__1::pair<int, int>, std::__1::__map_value_compare<int, int,
std::__1::less<int>, true>, std::__1::allocator<std::__1::pair<int, int> > >::operator='
requested here
__tree_ = _STD::move(__m.__tree_);
^
/usr/include/c++/v1/type_traits:2342:9: note: in instantiation of member function
'std::__1::map<int, int, std::__1::less<int>, std::__1::allocator<std::__1::pair<const
int, int> > >::operator=' requested here
__x = _STD::move(__y);
^
MapOfMaps.cpp:21:5: note: in instantiation of function template specialization
'std::__1::swap<std::__1::map<int, int, std::__1::less<int>,
std::__1::allocator<std::__1::pair<const int, int> > > >' requested here
std::swap<BaseType>(*this,t);
^
MapOfMaps.cpp:36:15: note: in instantiation of member function 'non_copyable_map<int, int,
std::__1::less<int> >::operator=' requested here
nestedMap[2] = std::move(inner);
^
/usr/include/c++/v1/memory:1918:7: note: candidate function (the implicit copy assignment
operator) has been explicitly deleted
class __compressed_pair
^
4 errors generated.
This may be a clang or libc++ bug (most likely libc++). I'm not duplicating your symptom with tip-of-trunk tools. The latest libc++ headers are here. This is a bit of a shot in the dark, but try this:
It looks like you're getting tangled up with this
swap
in<__bit_reference>
:which has nothing to do with maps. It just happens to be in scope.