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
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
()> > test;
class Test { public: vector<test> collection(); };
Try this:
struct my_requirements; typedef any
test; struct my_requirements mpl::vector<..., has_collection > {}; 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.h...
"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
()> 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
> _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
erased_collection; typedef any 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@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users