|
Boost : |
Subject: Re: [boost] Formal Review Request: TypeErasure
From: Steven Watanabe (watanabesj_at_[hidden])
Date: 2012-05-24 12:48:22
AMDG
On 05/23/2012 11:27 PM, Daniel Larimer wrote:
> 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.
>
It isn't as bad as you might think and I
know how to change the library to keep the
template instantation depth for the most
common errors down to 3 or 4.
> 3) How does using such an erasure effect compile times?
>
It's fairly slow. I've made no attempt to
optimize the metaprogramming at this point.
> 4) It is difficult to tell from the documentation, but what is the cost of dispatching methods via the any interface?
>
The cost is one call through a function pointer.
> 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'd say that this is out of scope for my
library currently.
> 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.
>
Reflection is really a separate issue.
> 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);
>
This is a nice interface, but it has several
limitations that I see no way around:
a) It supports member functions only
b) Overloading is impossible
Some problems can be solved with difficulty:
c) there's no way to know the number of arguments
at preprocessing time, so you can't declare
a regular function.
I think it would be possible to have a macro
that acts something like this for simple cases, though.
> 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.
>
I did use macros in the implementation.
Something like this wouldn't be very
hard to implement:
BOOST_TYPE_ERASURE_MEMBER(push_back, 2)
BOOST_TYPE_ERASURE_MEMBER(push_front, 2)
In Christ,
Steven Watanabe
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk