Boost logo

Boost :

From: Peder Holt (peder.holt_at_[hidden])
Date: 2004-09-01 02:01:14

On Tue, 31 Aug 2004 13:42:17 -0400, Arkadiy Vertleyb
<vertleyb_at_[hidden]> wrote:
> "Daniel James" <daniel_at_[hidden]> wrote
> > Still, his [Peder's] implementation is fantastic, considering that it runs
> on
> > Visual C++ 6.
> No doubt about this. As you can see, I hadn't even made this to be my goal.
> I've spent so much time in the past coping with various ICEs, ISOs, and
> ETIs, that I really, really want to avoid dealing with this compiler...
> > I wonder if it's worth combinig the two techniques. That is, using
> > partial specialisation to encode the type, but storing the value list as
> > 'compile-time constants' as in Peder's version. I think it should be
> > possible.
> At this point I am not even able to understand Peder's implementation, let
> alone the ability to combine techniques. It really looks more like a
> miracle to me:
> #define BOOST_TYPEOF(expr) \
> boost::type_of::decode<\
> boost::type_of::value_iterator<\
> sizeof(boost::type_of::encode_start(expr))\
> >\
> The value_iterator<> has just one integer parameter. How can decode<>
> deduce any type from it?!
> Regards,
> Arkadiy

Ok. I see what you do, and agree that on newer compilers, your code is
of the order O(N) (with your newest adjustments, even O(m))
I also see that your implementation requires the use of mpl, as you
require random access to the list of generated integers. This
introduces the before mentioned mpl limit of 60 (or around there)
which it turns out is difficult to bypass.
It would be awesome to have a forward iterator approach for the access
of integer values, as it would free you from the "chains" of mpl.

As to the implementation of my code,
I got the inspiration to my implementation from Daniel Wallins post
some time back on compile time constants:

As he states in his post, the solution is not portable. It relies on a
common compiler defect. Just for once MSVC's defects work with us in
stead of against us :)

I struggled quite a bit with the code myself before it dawned on me.
What gave me the insight, is that start_type (counter<10>) in reality
sets the maximum number of static constants you are allowed to define.

Each time a template class is instantiated, it generates two template
function overloads.
Before the compilation starts, a predefined check functions is defined:

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

At the first instantiation of set_variable, the function
size_type<1>::type check(counter<1>*)
is added to the function overload map.

(forget the T variable in the original post. It is of no use in
understanding the problem)

sizeof(check((counter<10>*)NULL)) will search for the best overload
available, and find the
size_type<1>::type check(counter<1>*) overload.

The next time set_variable is instantiated, the function
size_type<2>::type check(counter<2>*)
is added to the function overload map.

sizeof(check((counter<10>*)NULL)) will search for the best overload
available, and find the
size_type<2>::type check(counter<2>*) overload.

This is because counter<10> inherits from counter<9> inherits from ...
inherits from counter<2> inherits from counter<1>. Hence, counter<2>
is a better candidate then counter<1> because of the way the compiler
traverses the code,
In addition, another function is installed:
counter<N> value(counter<2>).

In my code, i use sizeof(check(counter<10>*)NULL)) to find the first
available counter index.
I then use sizeof(value((counter<iterator_value>*)NULL)) to find the
next encoded integer.

I am all for joining our efforts and creating a single typeof
implementation. typeof is even more needed for non-conforming
compilers to manage simple tasks as remove_pointer, remove_bounds etc.

> _______________________________________________
> Unsubscribe & other changes:

Boost list run by bdawes at, gregod at, cpdaniel at, john at