Boost logo

Boost Users :

Subject: [Boost-users] boost::ptr_vector does not support const types
From: Martin Gamwell Dawids (martin.dawids_at_[hidden])
Date: 2015-08-18 03:35:31


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



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net