
On Tue, 31 Aug 2004 13:42:17 -0400, Arkadiy Vertleyb <vertleyb@hotmail.com> wrote:
"Daniel James" <daniel@calamity.org.uk> 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: http://lists.boost.org/MailArchives/boost/msg69842.php 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: http://lists.boost.org/mailman/listinfo.cgi/boost