I would like to use a ptr_vector to hold a number of const values but it
seems ptr_vector does not currently support the use of const value types.
See this simple code example:
#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 svx;
std::vector 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 >,
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' – 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.)
Is there another workaround for this or have I overlooked something?
/Martin