Boost logo

Boost Users :

Subject: Re: [Boost-users] Indirectly 'recursive' type erasure
From: Steven Watanabe (watanabesj_at_[hidden])
Date: 2014-03-07 11:39:02


AMDG

On 03/06/2014 04:01 PM, Samuel Christie wrote:
> I'm trying to create a type erasure concept for a type that has a member
> function which can return a custom collection of itself.
>
> Having had little luck with the general formulation, I tried simplifying it
> to:
>
> BOOST_TYPE_ERASURE_MEMBER((has_collection), collection, 0);
>
> typedef any<
> mpl::vector<
> copy_constructible<>,
> typeid_<>,
> relaxed,
> has_collection<vector<_self>()>
> >
> > test;
>
> class Test {
> public:
> vector<test> collection();
> };
>

Try this:

struct my_requirements;
typedef any<my_requirements> test;
struct my_requirements
  mpl::vector<..., has_collection<vector<test>()> >
{};

The easiest way to handle a cyclic dependency
is to forward declare something, in this case
my_requirements, should do the trick.

> However, I get conversion errors if the Test::collection method returns
> either vector<Test> or vector<test>; it only seems to match if I have it
> literally return vector<_self>, which implies to me that I'm not
> understanding what I'm doing, and that _self isn't getting substituted in
> this case.
>

That is the expected behavior. See
http://www.boost.org/doc/libs/1_55_0/doc/html/boost_typeerasure/conceptdef.html

"The template parameters of the concept may involve placeholders. The
following are considered.

    Each template argument may be a cv and/or reference qualified
placeholder type.
    If a template argument is a function type, its arguments and return
type may be cv/reference qualified placeholders.

Any other placeholders are ignored."

> What do I need to do in order to be able to return types that are dependent
> on the erasure type?

It's technically possible for me to make has_collection<vector<_self>()>
work, but it would require a rather messy customization layer.
It can't be made to work automatically for any X<T> without help.

> My actual code uses a more indirect relationship, with
> the collection method returning a custom erased collection type that has an
> erased iterator that can dereference to the equivalent of Test. However,
> since there is still a form of cyclic dependency, I'm not really sure what
> I can do about it. I've tried using a custom struct based concept that had
> direct template arguments in the place of 'boost type erasure member', but
> I think I understand that technique even less, and it didn't seem to help
> much.
>
> It looked like there might be something useful under the Associated Types
> section of the type erasure documentation, but I couldn't quite figure it
> out.
>

It sounds like Associated Types may be
what you want for your real use case.
It would look something like this:

// Calculates the return type of T::collection()
template<class T>
struct get_collection_type {
  typedef std::vector<T> type;
};

typedef deduced<get_collection_type<_self> > _collection;

typedef mpl::vector<
    // requirements on test
    copy_constructible<>,
    typeid_<>,
    has_collection<_collection()>,
    // requirements on _collection
    copy_constructible<_collection>,
    // has_begin/has_end<_collection>
    // requirements on the iterator (using _self as the value_type)
> requirements;

typedef any<requirements> test;
typedef any<requirements, _collection> erased_collection;
typedef any<requirements, _iterator> erased_iterator;

Note that since test, the erased collection, and the
erased iterator have a cyclic dependency, the requirements
for them all need to be defined at once, for the library
to resolve it.

In Christ,
Steven Watanabe


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