Boost logo

Boost :

From: Peder Holt (peder.holt_at_[hidden])
Date: 2004-08-29 15:29:00


On Sun, 29 Aug 2004 16:34:54 +0100, Daniel James <daniel_at_[hidden]> wrote:
> Peder Holt wrote:
> > What would be very nice (but probably unattainable) was to reduce this
> > into an N process. Any suggestions would be most welcome.
>
> I've no idea how to do that, but I know how to get it to work with a
> macro like mine. And possibly improve normal use as well (although, I'm
> not sure about that).
<snip>
>
> http://myweb.tiscali.co.uk/calamity/code/typeof_vintage2.zip
>
> If you look at typeof.hpp and modifiers.hpp you should get a good idea
> of what I've done.
>

Neat. Definitely a saver for small types.

I thought of one potentially useful trick, that might theoretically
could reduce the number of calls to order N. By using the trick
presented by Daniel Wallin and Goran Mitrovic in another post,
conserning compile time constants:

template<int N> struct counter : counter<N - 1> {};
template<> struct counter<0> {};

template<int N>
struct size_type
{
  enum{value=N};
  typedef char(&type)[value + 1];
};

size_type<0>::type check(...);

template<class T, int N, int ID>
struct set_variable
{
  typedef counter<10> start_type;

  enum
  {
      current = sizeof(check((T*)0, (start_type*)0)) - 1,
      next = current + 1
  };

  friend typename size_type<next>::type check(T*, counter<next>*) {}
  friend typename size_type<ID>::type value(T*, counter<N>*) {}
};

#define CURRENT(T) (sizeof(check((T*)0, (counter<10>*)0)) - 1)
#define VALUE(T,N) (sizeof(value((T*)0, (counter<N>*)0)) - 1)
#define SET(T, N, ID) set_variable<T, N, ID>()

//TYPEOF macro...
typedef mpl::int_<CURRENT(int)> iterator_start;
invoke foo(expr,mpl::int_<CURRENT(int)>) somehow;
typedef mpl::int_<CURRENT(int)> iterator_end;
typedef decode<iterator_start,iterator_end>::type type;

Let each foo call SET(int,CURRENT(int)+1,CODE), where CODE represents the type.

Then VALUE(int,iterator_start::value) would give the compile time
constant of the first element, and VALUE(int,iterator_start::value+1)
for the next etc. etc.
This way, foo() would be called exactly as many times as the
expression is deep, and have no restrictions whatsoever (except
compiler limitations on template complexity) of the expression depth.
Only problem I have so far, is how to get the SET calls occur inside a
foo call before the type is defined. Perhaps do something like this:
template<typename T,int N>
foo(T*,set_variable<int,N,POINTER>);

template<typename T,int N>
foo(T&,set_variable<int,N,REFERENCE>);

and use sizeof of the expression in the end. I haven't tried this
trick yet, but I will certainly give it a shot.

> It's only tested on Visual C++ v6.0, and I expect it will probably
> require some changes to work on more recent versions. It needs to be
> cleaned up considerably, it's only really meant as a demonstration of
> the idea.
>
> I haven't really taken advantage of being able to do more encoding per
> call, that will probably require another rewrite and might not be
> practicle. So for normal use it's currently worse.
>
> But, when using BOOST_TYPEOF_TYPEDEF it does allow you to specify a
> higher number of calls to foo without loosing out for simpler types
> (since they only iterate a small number of times). It also generates
> slightly shorter value_lists, which reduces the number of iterations
> required. This could possibly be worthwhile?

Definitely. I will be looking at this approach more in detail if my
over-ambitious approach above fails :)

>
> If you've still got it, could I have another look at your original
> version? I deleted it when I downloaded your new one. It might be
> possible to use the techniques you used there for this type of
> implementation.
>
I put the source under:
http://groups.yahoo.com/group/boost/files/typeof_vintage_old.zip

I got an idea of how to improve the limit of this method.
Here is the way I encode templates:
template<>
struct encode_impl<BOOST_TYPEOF_UNIQUE_ID()>
{
  template<int Level>
  struct level {
     template<typename A0,typename A1,typename Types>
     struct encoder {
        typedef type_list<A0,type_list<A1,Types> > type_list;
        typedef Types BOOST_PP_CAT(types_,template_size);
        BOOST_STATIC_CONSTANT(int,value
=(encode_type<Level-1,types_0::type,types_1>::value));
     };
  };
  template<>
  struct level<0> {
     template<typename A0,typename A1,typename Types>
     struct encoder {
        BOOST_STATIC_CONSTANT(int,value = BOOST_TYPEOF_UNIQUE_ID());
     };
  };
};

Instead, It might be possible to do something like this:
template<>
struct encode_impl<BOOST_TYPEOF_UNIQUE_ID()>
{
  template<int Level>
  struct level {
     template<typename A0,typename A1,typename Types>
     struct encoder {
        BOOST_STATIC_CONSTANT(unsigned, depth0=depth<A0>::value);
        BOOST_STATIC_CONSTANT(unsigned, depth1=depth<A1>::value+depth0);
        BOOST_STATIC_CONSTANT(unsigned, depth=depth1+1);
        /*
        if Level<depth0, encode_type<Level-1,A0>
        else encode_type<Level-1,A1>
        I am not sure how the depth template should be implemented,
but this method should improve the limit from 10 values in value_list
to 10 template nestings.
     };
  };

--
Peder Holt
> thanks,
> 
> 
> 
> Daniel
> 
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
>

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