Boost.TypeErasure with forward declared type

81 Views Asked by At

Recently, I try to use boost.type_erasure with forward declared type as shown below:

#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/member.hpp>

struct Type;

BOOST_TYPE_ERASURE_MEMBER((HasTest), Test, 1)

using Any = boost::type_erasure::any <
    boost::mpl::vector <
    HasTest<void(Type&)>,
    boost::type_erasure::destructible<>,
    boost::type_erasure::relaxed
    >
>;

int main() {
    Any obj;
}

However, the compiler (e.g. clang) complains about incomplete type:

/usr/local/include/boost/type_traits/is_base_and_derived.hpp:228:42: error: incomplete type 'Type' used in type trait expression

    BOOST_STATIC_CONSTANT(bool, value = (BOOST_IS_BASE_OF(B,D) && ! ::boost::is_same<ncvB,ncvD>::value));

Finally, I have to work around by changing the API from reference to pointer, i.e. replacing Type& with Type*.

Problem:

Is it possible to make the code above work?

1

There are 1 best solutions below

3
Barry On

There's a few mistakes in your code. First, the macro BOOST_TYPE_ERASURE_MEMBER takes an argument for the number of arguments the member function takes. So you want:

BOOST_TYPE_ERASURE_MEMBER((HasTest), Test, 1)

Next, any is templated on a Concept, which can be a list of concepts. You forgot the list part, so you need:

using Any = any<boost::mpl::vector<
    HasTest<void(Type&)>,
    relaxed
    >>;

Otherwise, relaxed didn't get included in the Concept - which allows for default construction. Next, you didn't allow for destruction in your any, so you get compile errors on ~any(). You need to additionally provide destructible<>.

And lastly, you can define your Any with a forward-declared type. It just must be complete by the type you use it. The following compiles:

#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/member.hpp>

namespace mpl = boost::mpl;
using namespace boost::type_erasure;

struct Type;

BOOST_TYPE_ERASURE_MEMBER((HasTest), Test, 1)

using Any = any<mpl::vector<
    HasTest<void(Type&)>,
    relaxed,
    destructible<>
>>;

struct Type { };

int main() { 
    Any obj;
}