#include "boost/ptr_container/ptr_vector.hpp"
#include <vector>
class X
{
const int i;
public:
X(int i) : i(i) {}
int getI() const { return i; }
};
int main()
{
boost::ptr_vector<X> bvx;
boost::ptr_vector<const X> bvcx;
std::vector<X*> svx;
std::vector<const X*> svcx;
bvx.push_back(new X(42));
bvcx.push_back(new X(42)); // does not compile
svx.push_back(new X(42));
svcx.push_back(new X(42));
return 0;
}
I have tried this on MSVC 2005/8.0 and with g++ on Mac – i.e. Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn).
On both compilers, calling 'push_back()' on a 'boost::ptr_vector<const X>' does not compile and on g++/Mac it yields this error message:
../boost/boost/ptr_container/ptr_sequence_adapter.hpp:249:37: error: reference to type 'const value_type'
(aka 'void *const') could not bind to an lvalue of type 'value_type' (aka 'const X *')
this->base().push_back( x ); // strong, commit
^
ptr_vector_test.cpp:22:8: note: in instantiation of member function 'boost::ptr_sequence_adapter<const X,
std::__1::vector<void *, std::__1::allocator<void *> >, boost::heap_clone_allocator>::push_back'
requested here
bvcx.push_back(x);
^
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/vector:697:62: note: passing argument to
parameter '__x' here
_LIBCPP_INLINE_VISIBILITY void push_back(const_reference __x);
^
1 error generated.
So the problem occurs when the passed value of type 'const X*' needs to be pushed to the backing 'std::vector<void*>' – i.e. a non-const 'void*' element type.
The same problem exists for push_front().
A simple fix for 'push_back()' (and similar for 'push_front()') is to modify the file 'ptr_sequence_adapter.hpp' adding a cast of the value before pushing is:
--- a/include/boost/ptr_container/ptr_sequence_adapter.hpp
+++ b/include/boost/ptr_container/ptr_sequence_adapter.hpp
@@ -246,7 +246,7 @@ namespace ptr_container_detail
this->enforce_null_policy( x, "Null pointer in 'push_back()'" );
auto_type ptr( x ); // notrow
- this->base().push_back( x ); // strong, commit
+ this->base().push_back( (void*) x ); // strong, commit
ptr.release(); // nothrow
}
I am using a C-style cast as neither 'const_cast' nor 'reinterpret_cast' can be used here.
(I know the formatting of the comments should also be fixed, but that would make my diff here more difficult to read.)