Boost logo

Boost Users :

From: Terry G (tjgolubi_at_[hidden])
Date: 2006-11-07 14:29:08


>> I've just finished reading C++ Template Metaprogramming again.
>> I just don't get it.
>>
>> Why would someone use a type container?
>>
>> I have used enable_if, along with some of the logic functions for
>> managing
>> an overload set.
>> Otherwise, I'm clueless.
>>
>> I'd really like a reference to an MPL primer or some case studies.
>
> The book contains a case study in which type sequences are used to
> describe the rows of a state machine's transition table. Was that not
> a sufficient motivating case?

FSMs are not something I'm familiar with. I didn't really notice the vector
of rows until recently.
How is the FSM approach in your book better than arrays of structs?
I didn't see any advantage, and the supporting code is too complex.
There must be an advantage, otherwise, why would you work so hard to write
these things?
I'll try to implement a reusable FSM framework, without MPL.
Then, perhaps, advantages/disadvantages of MPL would be more apparent to me.
Is there a good way to post hundreds of SLOCs for discussion? I don't have
a website.

BTW, on the boost website, there are three versions of the FSM player
example.
A ReadMe.txt to explain the differences would be helpful.

>> Too much pain with very little gain.
>
> What, specifically, do you find painful?

Well, you asked...
I write stuff that I think should work, but the compiler issues tons of
error messages.
Pitfalls like when to use typename.
Brain cramps trying to comprehend the compile-time/run-time boundary.
Recently, I tried to avoid using a large 150-case switch statement using
metaprogramming.
Each MessageNN has a unique static const int TAG member. They all derive
from a common Message base class that has the common message header,
including the tag.
The only thing each case did was something like.
    switch (msg.tag()) {
       case Message26::TAG:
         cout << static_cast<const Message26&>(msg) << endl;
         break;
       case Message27::TAG:
          cout << static_cast<const Message27&>(msg) << endl;
          break;
       ...
    }
That is, upcast a received message (over a wire) and print it. Virtual
functions cannot be used because the message can have no vtbl.
I eventually just did the big switch like I have for twenty years.
The pain (frustration) comes from believing there's a "better" way, but not
knowing how to realize it.
Pain, too, because without a mentor to guide me, I feel like I'm walking
around trying to drive in screws with my shiny new hammer.
Painful because after you get a nifty mpl::vector of MessageTypes, you
realize after the 50th message, that it won't scale up to 150.
Painful because compile times take much longer. (VC8 takes a lot longer,
not sure why).
Painful because I don't understand the runtime and memory trade-offs
anymore.

i.e. painful because it makes me realize how stupid I still am, in spite of
all my past successes. Printf and void* have served me well.

>> Time to ask for help.
>> Rereading this, it sounds negative.
>> Really, I think the MPL is really cool!
>
> Cool, how can we help?

Do know how to do a mind-meld? (Spock recoiled, his face white with shock.
He had never experienced such chaos before.)
I need to be patient and ask one question at a time. There is a lot of
really difficult material packed into a deceptively slim book.

So, back to that switch statement... is there a better way?
I thought of using something like:

template <Tag> struct DerefTag { typedef Message type; }

And then specializing it like this.

template <> struct DerefTag<Message26::TAG> { typedef Message26 type; }

But that can only be used with compile-time constants, limiting its
usefulness.

Now I can write each case statement like this:

case Message26::TAG:
   cout << static_cast<const DerefTag<Message26::TAG>::type&>(msg) << endl;
   break;

That's not better, its worse. Sigh. Should I give up? Is there a better
way?

BTW, how do compilers handle big switches? How do they find the matching
case?
Would an stl::map or sorted stl::vector of callback functors yield better
portable performance?
Hmmm... (<--- the sound I make before wasting even more time).

terry


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net