Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2003-01-07 10:03:19


"Yitzhak Sapir" <yitzhaks_at_[hidden]> writes:

> The original version I suggested used fold, and for that, you do
> need to use if_ since you need to determine whether to call
> Prev::eval(). I didn't post my implementation since it took me
> quite a while to get it working with VC6.5 and I thought only the
> general concepts were necessary, not a full blown example.

> In any
> case, I think just using if_ and type traits lacks the "small rush
> of excitement when you see it work."

Yeah, it doesn't do very well in that department.

> Regarding the "much more code," metaprogramming is used to produce a
> lot of inline code in Blitz style templates. This is considered a
> type of optimization, mainly in speed. If there weren't a
> cout.write, I think my example would work faster than the equivalent
> of using streaming operators <<.

Dave's mention of efficiency was the weakest part of the argument, but
significant nonetheless.

> As for usefulness, I agree that the next thought after the rush of
> excitement, is "so what?" I could argue that doing for_each on the
> vector_c is not different than doing for_each on a compile time
> vector of types. In fact, the functor receives a type, not a
> character.

Yep. I'm nervous about showing iteration and sequences in a this
example, though. There's nothing that sophisticated going on in
"hello, world."

> Generation of long sequences of code is one use of metaprogramming.
> A vector of pairs, might be used to implement read serialization of
> a discriminated union. This is much more useful, whether for a
> library author or not, but much more complex for a beginning example
> to understand:
...

Sure, it's comparitively easy to come up with useful examples that are
more complicated. Incidentally, yours needs some tweaks for
generality. The main reason is that for_each tries to
value-initialize an instance of each of the types it processes and
passes that to the function object. If the type isn't
default-constructible, it won't compile. I'm not sure that preserving
this property is worthwhile. Opinions, Aleksey?

typedef list<
   pair<int_c<0>, int>
 , pair<int_c<1>, double>
 , pair<int_c<2>, string>
> typelist;

int discriminator;
stream >> discriminator;
variant<transform<typelist,select2nd>::type> v;

for_each<typelist, wrap>(serialize_if_appropriate(discriminator, stream, v));
                   ^^^^
with the following definition:

struct serialize_if_appropriate
{
public:
   ...
   template <class W>
   void operator()(W&) const
   {
      typedef W::type T; // <--

      if (T::first::value == discriminator) {
          T::second::type t;
          stream >> t;
          v = t;
      }
   }

private:
   istream& stream;
   int discriminator;
   variant<typelist> v;
};

-- 
                       David Abrahams
   dave_at_[hidden] * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution

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