Boost logo

Boost Users :

Subject: Re: [Boost-users] Indirectly 'recursive' type erasure
From: Samuel Christie (schrist_at_[hidden])
Date: 2014-03-11 16:42:14


Ok, that looks very promising. I was able to get the simple example at the
top to work, returning a vector of pre-erased test objects, but I had some
more trouble with the later one. My current test structure looks like:

class Test;

class Collection {
  class iterator {
  public:
    explicit iterator(int i) : index(i) {};
    iterator& operator++();
    Test operator* () const;
    bool operator== (const iterator& other) const;
    int index;
  };
public:
  Collection(int i) :value(i) { };
  friend iterator begin(Collection& c);
  friend iterator end(Collection& c);
  int value;
};

class Test {
public:
  Collection collection();
};

I'm not sure how to do the get_collection_type deduction in such a way that
it works for more than one type of collection. I.e., both a vector<T> and a
Collection as defined above.

I also tried to do a test with the slightly more basic vector<Test>
collection type. I got close, but I eventually had issues with the !=
required by the foreach loop pattern.

Here's a paste of most of the test code: pastebin.com/GiQwQTcq

Hopefully what I'm having trouble with makes sense to you; if not, maybe
just providing a few more examples of the pieces required to make a
for(auto i : t.collection()) work based on the above class declaration
would be helpful. I feel like either I'm getting close, or I'm trying to do
something I shouldn't be.

On Fri, Mar 7, 2014 at 11:39 AM, Steven Watanabe <watanabesj_at_[hidden]>wrote:

> 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 mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>



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