views:

233

answers:

3

This is from TTL:

////////////////////////////////////////////////////////////
//  run-time type switch
template <typename L, int N = 0, bool Stop=(N==length<L>::value) > struct type_switch;

template <typename L, int N, bool Stop>
  struct type_switch
  {
    template< typename F >
      void operator()( size_t i, F& f )
      {
        if( i == N )
        {
          f.operator()<typename impl::get<L,N>::type>();
        }
        else
        {
          type_switch<L, N+1> next;
          next(i, f);
        }
      }
  };

It's used for typeswitching on a TypeList. Question is -- they are doing this via a series of nested if's. Is there a way to do this type switch as a single select statement instead?

Thanks!

A: 

I don't think so.

This kind of template metaprogramming is normally done with recursion. Since it all happens at compile-time, I wouldn't be surprised if there's no runtime recursion or condition-checks.

UncleBens
+1  A: 

You'll need the preprocessor to generate a big switch. You'll need get<> to no-op out-of-bound lookups. Check the compiler output to be sure unused cases produce no output, if you care; adjust as necessary ;v) .

Check out the Boost Preprocessor Library if you care to get good at this sort of thing…

template <typename L>
  struct type_switch
  {
    template< typename F >
      void operator()( size_t i, F& f )
      {
        switch ( i ) {
         #define CASE_N( N ) \
         case (N): return f.operator()<typename impl::get<L,N>::type>();
         CASE_N(0)
         CASE_N(1)
         CASE_N(2)
         CASE_N(3) // ad nauseam.
      }
  };
Potatoswatter
If you go *ad nauseam*, wouldn't it mean that at some point the switch would try to instantiate a template with potentially invalid N and the whole thing fails to compile? Recursion knows where to stop, this switch apparently doesn't. (Basically it seems to me that the whole switch idea is completely misguided, and not a way to go about in template metaprogramming. IMO, a compile-time switch is nothing but an if-chain created through recursion.)
UncleBens
@UncleBens: That's what I meant by "no-op out-of-bound lookups". The typelist template implements recursion by itself in `get<>`; it should detect an out-of-bounds index and return nothing. As for advantage over an if-chain, that depends on the compiler and the application. According to the answer to a duplicate question, boost::variant (a much better-known example) uses the technique I outlined here.
Potatoswatter
@Potatoswatter : i just want to apologize for asking nearly the same question twice after your answer. Problem -- I didn't comprehend your answer at first; but now that I understand it, I can see why my other questions were redundant.
anon
@anon: no biggie, I was being dramatic esp since the situation was funny. OK to ask questions, too…
Potatoswatter
A: 

You could always use a binary search instead of a linear search. It would be more complicated and more likely to have bugs in it (binary search is surprisingly easy to mess up).

You could also manually expand out N type_switch::operator(), where N is some reasonable upper bound on the number of typelist lengths you will have in your program.

MSN