Search code examples
c++boostmove-semanticsboost-type-erasure

Is boost type_erasure::any allocation on move avoidable?


When I move a boost::type_erasure::any object like in this test case:

#include <boost/type_erasure/any.hpp>

#include <string>

int main() {
    typedef ::boost::mpl::vector<
        boost::type_erasure::destructible<>,
        boost::type_erasure::constructible<boost::type_erasure::_self(
            boost::type_erasure::_self&&)> >
        my_concept;
    typedef boost::type_erasure::any<my_concept> my_any;

    my_any a1(std::string("Test"));
    my_any a2 = std::move(a1); // dynamic memory allocation here
}

I get a dynamic memory allocation in the move construction of a2 within boost/type_erasure/constructible.hpp

template<class R, class... T>
struct constructible<R(T...)>
{
    static ::boost::type_erasure::detail::storage
    apply(T... arg)
    {
        ::boost::type_erasure::detail::storage result;
        result.data = new R(::std::forward<T>(arg)...);
        return result;
    }
};

Since I'm moving from a1 I was hoping that the new for the storage could be avoided by taking a1s storage. I have however failed to get rid of the memory allocation on move. Is this allocation avoidable?

I can see the new being hit by setting a breakpoint and it showed up in my benchmarks in the context of a larger application.

I'm hoping to not hit the result.data = new R(::std::forward<T>(arg)...);. I tried finding a concept that helps but didn't get it to work.


Solution

  • When you move-from an any, the source any does not become empty. It instead contains a moved-from object.

    In order to implement your optimization, it would need to become empty. And I see no support for destructive-move in boost type erasure's any.

    The difficulty of expressing destructive move is a flaw in the current C++ move/copy semantics model, so this lack isn't all that surprising.