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<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.)

Is there another workaround for this or have I overlooked something?


/Martin