Hi,
2010/7/28 Hite, Christopher <[email protected]>:
>> Generally without knowing the compiler version you are using
>> it is hard to tell.
> I'll use whatever's best. Right now I'm still on 4.4.3. I'll probably
> upgrade soon to 4.5.
>
>> The same is true without a complete compilable testcase.
> I didn't want to make a test case that depends on boost::mpl. How's
> this:
>
> struct DecodeContext;
>
> struct M1{
> static const int id=1;
> static void decode(DecodeContext& ){}
> };
>
> struct M2{
> static const int id=2;
> static void decode(DecodeContext& ){}
> };
>
> struct M3{
> static const int id=3;
> static void decode(DecodeContext& ){}
> };
>
>
> template <int> struct ListMember;
>
> template <> struct ListMember<1>{ typedef M1 type; };
> template <> struct ListMember<2>{ typedef M2 type; };
> template <> struct ListMember<3>{ typedef M3 type; };
>
> template<int i>
> void foo(int id, DecodeContext& dc) {
> typedef typename ListMember<i>::type M;
> if(M::id==id)
> M::decode(dc);
> else
> foo<i-1>(id,dc);
> }
>
> template<>
> void foo<0>(int id, DecodeContext& dc) {}
>
>
>
> int main(){
> DecodeContext& dc= *(DecodeContext*)0;// junk for now
> int id=2; //sometime runtime dependent
> foo<3>(id,dc);
> return 0;
> }
>
>
>> You can use the flatten attribute to tell the compiler to inline all
>> calls in a given function, like
>>
>> void __attribute__((flatten)) foo(void)
>> {
>> ...
>> decode1();
>> ...
>> }
>
> That would cause decode1() to be inlined, which might not be what you
> want.
>
> Hmm maybe I could rewrite things so the switch case returns a function
> pointer. I'm guessing that would make things slower though.
>
Or you could just initialize static array of pointers, like that
(please note, that I never compiled code below):
typedef void (*pfn) (DeclContext&);
tempate <int I>
struct InitDispatchHelper
{
static void init(std::tr1::array<pfn,N>& a)
{
a[I-1] = ListMemeber<I-1>::foo;
InitPointersHelper<I-1>::init(a);
}
};
// End recursion
template<>
struct InitDispatchHelper
{
static void init(std::tr1::array<pfn,N>& a)
{ /*does nothing */ }
};
// Dispatch table;
template <int N>
struct DispatchFoo : std::tr1::array<pfn, N>
{
DispatchFoo() : std::tr1::array<pfn, N>()
{
InitDispatchHelper<N>::init(*this);
}
};
then your call would look like:
static const int X = /* your maximal I in ListMembers meta-class */
void call_foo(int i, DeclContext& c)
{
static const DispatchFoo<X> foo_dispatch;
foo_dispatch[i] (c);
}
Bonus points for benchmarking both solutions and making it policy
class choosing between those two solutions depending on X.
Good luck,
Piotr