Boost logo

Boost :

Subject: Re: [boost] Formal Review Request: TypeErasure
From: Daniel Larimer (dlarimer_at_[hidden])
Date: 2012-05-24 02:27:13


I read the docs as this library is very impressive and does some of the same things I do with Boost.Reflect so I can appreciate the problem domain.

http://bytemaster.github.com/boost_reflect/group__boost__reflect__quickstart.html#boost_reflect_erasures

I would like to make comments / ask some questions:

1) More motivating examples would be useful. Given the difficulty (verbosity/boiler plate) of implementing 'push_back', I cannot imagine using this library as an 'end coder' for custom interfaces. The only place I could see using anything other than the built in concepts would be to simplify the development of my own APIs for my users sake, not mine.

1.1) better documentation on what all of the template parameters mean and why they are used would be helpful.

2) I cannot begin to imagine the template errors generated by using such a complex type. But this is par for the course with Boost.

3) How does using such an erasure effect compile times?

4) It is difficult to tell from the documentation, but what is the cost of dispatching methods via the any interface?

5) Many scripting languages have a generic value that could be an int, double, string, bool, array, map, or function. This could perhaps belong to a new type... boost::type_erasure::variant<conceptA,conceptB,etc>

I have recently been working on a new interface along those lines:
https://github.com/bytemaster/boost_reflect/blob/master/tests/value_test.cpp

struct sub_val {
   std::string happy;
  double day;
};
BOOST_REFLECT( sub_val, (happy)(day) );

struct test {
  std::string b;
  sub_val sub;
  std::vector<sub_val> data;
};
BOOST_REFLECT( test, (a)(b)(sub)(data) )

test t(1,"test_ref");
t.sub.happy = "oh happy pie day";

value_cref v(t); // const ref
value vc(t); // copy
value_ref vr(t); // regular ref

BOOST_ASSERT( v["sub"]["happy"].as<std::string>() == "oh happy pie day" );

Yours has compile-time checking and supports many more concepts. Mine does runtime checking and throws on error.

I would like to compare your approach with mine in boost::reflect to show various tradeoffs.

I think our work has different strengths and weaknesses and I would love to find a way to blend it.

Compare:
struct vector_concept {
        void push_back( int );
        void push_front (int);
        int size();
        int front();
        int at(int);
};
BOOST_REFLECT_ANY( vector_concept, (push_back)(push_front)(size)(front)(at) )

boost::reflect::any_ptr<vector_concept> v( new std::vector<int>() );
v->push_back(5);

The way I see it, I was able to define 5+ methods on an interface in one line of easy to understand code. If you could achieve something like this with your library then it would be a huge win.
Mine is implemented in a manner that results in sizeof(reflect::any_ptr) to grow with each member such as 'push_back' is really a public member functor. Your approach does not have this overhead.
My approach allows visiting each member and dynamically specifying an implementation. Yours enables many more concepts (operators, etc) to be implemented. Mine could be used by any coder, yours requires one that can throughly understand templates and debug all manner of 'place holders'. I consider myself skilled and would expect to have trouble implementing something like push_back, especially if it required complex usage of place holders. Better documentation could help.

Clearly we are solving slightly different problems, and I would love to use your library as a high performance, lower overhead version of my reflect::any_ptr<> class in places where I do not need some of the more dynamic features.

Good job! I would probably vote to include it based upon the built-in concepts alone. Some fancy macro help would seal the deal.

Dan


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk