Search code examples
c++boostboost-variantboost-any

Is it possible to use boost::any or boost::variant with a boost::pool?


boost::any:

I tried to compile and run the following code to test this:

#include <boost/any.hpp>
#include <boost/pool/object_pool.hpp>

int main()
{
  boost::object_pool<boost::any> pool;
  boost::any *i = pool.malloc();
  *i = 1;

  boost::any *j = pool.construct(2);

  pool.destroy(i);
  pool.destroy(j);
}

But it gets a segfault in the boost::any destructor.

boost::variant:

Trying to compile and run the following:

#include <boost/any.hpp>
#include <boost/pool/object_pool.hpp>
#include <boost/variant.hpp>

int main()
{
  typedef boost::variant<int, double> my_variant;

  boost::object_pool<my_variant> pool;
  my_variant *i = pool.malloc();
  *i = 1;

  my_variant *j = pool.construct(2);

  pool.destroy(i);
  pool.destroy(j);
}

And I got the following error:

a.out: visitation_impl.hpp:207: typename Visitor::result_type boost::detail::variant::visitation_impl(int, int, Visitor&, VPCV, mpl_::true_, NBF, W*, S*) [with W = mpl_::int_<20>; S = boost::detail::variant::visitation_impl_step, boost::mpl::l_iter >; Visitor = boost::detail::variant::invoke_visitor

; VPCV = void*; NBF = boost::variant::has_fallback_type_; typename Visitor::result_type = bool; mpl_::true_ = mpl_::bool_]: Assertion `false' failed. Aborted (core dumped)

Is this expected behavior? Does the boost::pool only work for simple C++ types like int, doble, float, etc?


Solution

  • Yes, boost pool works with both. You're simply using it wrong.

    CAVEAT: There's really no use at all to use a pool allocator with boost::any because it will dynamically allocate the held value outside of the pool.

    But this doesn't mean that you can't if you use it right.

    malloc only allocates uninitialized memory. It's your error to expect to be able to assign to it as if it were a fully functional instance of the object type that the point implies.

    T *i = pool.malloc();
    new (i) T();
    

    This fixes it:

    Live On Coliru

    #include <boost/pool/object_pool.hpp>
    #include <boost/any.hpp>
    #include <boost/variant.hpp>
    
    template <typename T>
    void run_test() {
        boost::object_pool<T> pool;
    
        T *i = pool.malloc();
        new (i) T();
        *i = 1;
    
        T *j = pool.construct(2);
    
        pool.destroy(i);
        pool.destroy(j);
    }
    
    int main() {
        run_test<boost::variant<int, double> >();
        run_test<boost::any>();
    }
    

    This also runs clean under asan/ubsan and valgrind.

    Bonus Question

    Is this expected behavior? Does the boost::pool only work for simple C++ types like int, doble, float, etc?

    For POD types or trivial types you could get away with eliding the constructor, much like the C++ compiler is allowed to elide them in those cases.