
From: Boost [mailto:boost-bounces@lists.boost.org] On Behalf Of Steven Watanabe
On 03/18/2013 08:30 AM, Andy Jost wrote:
Maybe looking at some code would help clarify the answers to these questions. I have about 300 lines partially implementing an adaptor for std::set using Boost.TypeErasure, plus a list of questions and problems I encountered. Is that too large to put into an email for this list? If so, where can I drop it?
That shouldn't be too large.
Ok, code is at the end; questions first. I realize many of these questions may be answered in the documentation.
Linux 2.6.9-89.ELlargesmp x86_64
g++ (GCC) 4.5.2
1) Certain functions require a downcast, of sorts. The overload of std::set<T>::insert taking an iterator as hint is an example. Not just any iterator, but one with exactly the right type is needed. Maybe this is what type_erasure::is_same is for, but I haven't looked into it yet.
2) I start getting errors when the mpl::vector of requirements exceeds 20 elements: "error: wrong number of template arguments (21, should be 20)."
As a blind guess, I tried including boost/mpl/vector/vector30.hpp but it doesn't help. I know there's a good chance the answer is in the MPL docs somewhere, but I haven't had a chance to go deeper.
3) I could not implement swap. If item 1 can be resolved, then this could work in the same way. Still, it seems that two any<> objects of the same type should be swappable (though, it is not obvious how that would be expressed). I couldn't find a way to do it.
4) When members are overloaded based on a constant this, I could only use the const-qualified version. So, I can add a requirement for set<T>::clear, but for set<T>::begin, the return value must be specified as const_iterator.
5) BOOST_TYPE_ERASURE_MEMBER cannot be used in a SEQ_FOR_EACH loop, because it uses SEQ_FOR_EACH internally. It would be handy to have a way to declare several members when the namespace path and prefix (e.g., has_) doesn't change, either by passing the z parameter or using another macro.
6) I could never get the bidirectional_iterator concept from TypeErasure working. I didn't find an example. I ended up writing out the requirements myself. Also, that required the use of relaxed and I didn't understand why.
#define BOOST_TYPE_ERASURE_STL_MEMBER(key,name,arity) \
BOOST_TYPE_ERASURE_MEMBER((boost)(type_erasure)(has_##key),name,arity); \
/**/
/* std::allocator */
BOOST_TYPE_ERASURE_STL_MEMBER(address,address,1)
BOOST_TYPE_ERASURE_STL_MEMBER(allocate1,allocate,1)
BOOST_TYPE_ERASURE_STL_MEMBER(allocate2,allocate,2)
BOOST_TYPE_ERASURE_STL_MEMBER(construct,construct,2)
BOOST_TYPE_ERASURE_STL_MEMBER(deallocate,deallocate,2)
BOOST_TYPE_ERASURE_STL_MEMBER(destroy,destroy,1)
/* Iterators */
BOOST_TYPE_ERASURE_STL_MEMBER(begin,begin,0)
BOOST_TYPE_ERASURE_STL_MEMBER(end,end,0)
BOOST_TYPE_ERASURE_STL_MEMBER(rbegin,rbegin,0)
BOOST_TYPE_ERASURE_STL_MEMBER(rend,rend,0)
/* Capacity */
BOOST_TYPE_ERASURE_STL_MEMBER(empty,empty,0)
BOOST_TYPE_ERASURE_STL_MEMBER(max_size,max_size,0)
BOOST_TYPE_ERASURE_STL_MEMBER(size,size,0)
/* Modifiers */
BOOST_TYPE_ERASURE_STL_MEMBER(clear,clear,0)
BOOST_TYPE_ERASURE_STL_MEMBER(erase1,erase,1)
BOOST_TYPE_ERASURE_STL_MEMBER(erase2,erase,2)
BOOST_TYPE_ERASURE_STL_MEMBER(insert1,insert,1)
BOOST_TYPE_ERASURE_STL_MEMBER(insert2,insert,2)
BOOST_TYPE_ERASURE_STL_MEMBER(swap,swap,1)
/* Observers */
BOOST_TYPE_ERASURE_STL_MEMBER(key_comp,key_comp,0)
BOOST_TYPE_ERASURE_STL_MEMBER(value_comp,value_comp,0)
/* Operations */
BOOST_TYPE_ERASURE_STL_MEMBER(count,count,1)
BOOST_TYPE_ERASURE_STL_MEMBER(equal_range,equal_range,1)
BOOST_TYPE_ERASURE_STL_MEMBER(find,find,1)
BOOST_TYPE_ERASURE_STL_MEMBER(lower_bound,lower_bound,1)
BOOST_TYPE_ERASURE_STL_MEMBER(upper_bound,upper_bound,1)
/* Allocator */
BOOST_TYPE_ERASURE_STL_MEMBER(get_allocator,get_allocator,0)
#define BOOST_TYPE_ERASURE_FWD_TYPEDEFS(z,base,name) typedef base::name name;
#define BOOST_TYPE_ERASURE_STL_TYPEDEFS \
(key_type)(key_compare)(value_compare)(allocator_type) \
(iterator)(const_iterator)(reverse_iterator)(const_reverse_iterator) \
BOOST_TYPE_ERASURE_ALLOCATOR_TYPEDEFS \
/**/
#define BOOST_TYPE_ERASURE_ALLOCATOR_TYPEDEFS \
(value_type)(reference)(const_reference)(pointer)(const_pointer) \
(difference_type)(size_type) \
/**/
namespace boost { namespace type_erasure
{
template<typename T> struct allocator_typedefs
{
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef const T* const_pointer;
typedef const T& const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
};
template