2011-09-21 9 views
2

J'ai une fonction ennuyeuse à exécuter, je veux passer en boucle pour économiser cette fois (j'ai toutes les données), mais cela nécessite des types. Y at-il un moyen de faire un tableau de types, ou avoir quelque chose en temps réel pour le faire? (Si cela aide, j'ai 3 types et je veux exécuter la méthode avec tous les types contre tous les types).Looping typedefs

fprintf(stdout, "Testing UTF-32...\n"); 
testUTF<uint32_t, uint32_t>(&testEncs[0], &testEncs[0]); 
testUTF<uint32_t, uint16_t>(&testEncs[0], &testEncs[1]); 
testUTF<uint32_t, uint8_t> (&testEncs[0], &testEncs[2]); 

fprintf(stdout, "Testing UTF-16...\n"); 
testUTF<uint16_t, uint32_t>(&testEncs[1], &testEncs[0]); 
testUTF<uint16_t, uint16_t>(&testEncs[1], &testEncs[1]); 
testUTF<uint16_t, uint8_t> (&testEncs[1], &testEncs[2]); 

fprintf(stdout, "Testing UTF-8...\n"); 
testUTF<uint8_t, uint32_t>(&testEncs[2], &testEncs[0]); 
testUTF<uint8_t, uint16_t>(&testEncs[2], &testEncs[1]); 
testUTF<uint8_t, uint8_t> (&testEncs[2], &testEncs[2]); 
+2

Mon intuition me dit que cela peut être résolu avec le métaprogrammation de gabarit. – Nawaz

+0

Ainsi que le mien, mais cela impliquerait aussi des définitions. Cela semble être une chose malpropre à faire. – Jookia

Répondre

7
template <int I> struct UType; 
template <> struct UType<0> { typedef uint32_t Type; }; 
template <> struct UType<1> { typedef uint16_t Type; }; 
template <> struct UType<2> { typedef uint8_t Type; }; 
static const int n_types = 3; 

template <int A,int B> 
struct Test { 
    typedef typename UType<A>::Type AType; 
    typedef typename UType<B>::Type BType; 
    static void test() 
    { 
    testUTF<AType,BType>(&testEncs[A],&testEncs[B]); 
    Test<A,B+1>::test(); 
    } 
}; 

template <int A> 
struct Test<A,n_types> { 
    static void test() { Test<A+1,0>::test(); } 
}; 

template <> 
struct Test<n_types,0> { 
    static void test() { } 
}; 

void testAll() 
{ 
    Test<0,0>::test(); 
} 
+0

Ça a l'air génial, mais je pense que je vais juste générer une boucle déroulée en externe. – Jookia

+0

Avec l'édition cela fonctionne comme un charme. Incroyable! +1 – Stephan

+0

Après beaucoup d'évaluation, je pense que je vais utiliser cela. – Jookia

0

Une façon de le faire serait d'écrire un autre programme (dans votre Lanugage favori) pour générer le code C++ nécessaire pour ce test. Vous pouvez construire ce générateur de code dans votre système de construction, ou simplement l'exécuter une fois et enregistrer le code C++ de sortie.

+0

C'est peut-être ce que je finis par faire vu que certains d'entre eux sont déjà externes. – Jookia

1

Vous pouvez appeler les tests de manière récursive. (Ce n'est pas ce que vos tests ressemblent, mais il pourrait être fait la même)

template<typename Next, typename Impl> 
struct Tester 
{ 
    template<typename FwdIter> 
    static void Test(FwdIter first, FwdIter last) 
    { 
     for(FwdIter it = first;it != last; ++it) 
      Impl::TestImpl(*first, *it); 
     Next::Test(first, last); 
    } 
}; 

struct EndTest 
{ 
    template<typename FwdIter> 
    static void Test(FwdIter first, FwdIter last) { } 
}; 

template<typename Next> 
struct TestA : Tester<Next, TestA<Next>> 
{ 
    static void TestImpl(int a, int b) 
    { 
     std::cout << "A" << a << b <<"\n"; 
    } 
}; 

template<typename Next> 
struct TestB : Tester<Next, TestB<Next>> 
{ 
    static void TestImpl(int a, int b) 
    { 
     std::cout << "B" << a << b <<"\n"; 
    } 
}; 

int main() 
{ 
    TestA<TestB<EndTest>> test; 
    std::array<int, 3> values = {1, 2, 3}; 
    test.Test(values.begin(), values.end()); 
    return 0; 
} 
0

Encore un autre outil pour marcher à travers typelist (j'aime classes de types):

#include <stdint.h> 
#include <typeinfo> 
#include <iostream> 

// typeclass 

/* 
* Concept: 
* struct typedseq_traits<T> 
* { 
*  enum { is_empty = 0 }; 
*  static SomeType head(const T &); 
*  static TailTypes tail(const T &); // typedseq_traits<TailTypes> 
* } 
*/ 

template<class T> 
struct typedseq_traits; 


template<class T, class F, int is_empty> 
struct typedseq_foreach_step; 

template<class T, class F> 
struct typedseq_foreach_step<T,F,1> 
{ 
    static void walk(F &func, const T &seq) 
    {} 
}; 

template<class T, class F> 
struct typedseq_foreach_step<T,F,0> 
{ 
    static void walk(F &func, const T &seq) 
    { 
     func(typedseq_traits<T>::head(seq)); 
     typedseq_foreach(func, typedseq_traits<T>::tail(seq)); 
    } 
}; 


template<class T, class F> 
void typedseq_foreach(F &func, const T &seq) 
{ 
    typedseq_foreach_step<T,F,typedseq_traits<T>::is_empty>::walk(func, seq); 
} 

// instances 

struct typelist_empty {}; 

template<class H, class T> 
struct typelist_cons {}; 

template<> 
struct typedseq_traits<typelist_empty> 
{ 
    enum { is_empty = 1 }; 
}; 

template<class H, class T> 
struct typedseq_traits<typelist_cons<H,T> > 
{ 
    enum { is_empty = 0 }; 
    static H head(const typelist_cons<H,T> &seq) { return H(); } 
    static T tail(const typelist_cons<H,T> &seq) { return T(); } 
}; 

// usage 

typedef typelist_cons<uint8_t, typelist_cons<uint16_t, typelist_cons<uint32_t, typelist_empty> > > mylist; 

template<class T1> 
struct func2 
{ 
    template<class T2> 
    void operator()(T2) 
    { 
     std::cerr << typeid(T1).name() << ", " << typeid(T2).name() << std::endl; 
    } 
}; 

struct func1 
{ 
    template<class T1> 
    void operator()(T1) 
    { 
     func2<T1> f; 
     typedseq_foreach(f, mylist()); 
    } 
}; 

int main() 
{ 
    func1 f; 
    typedseq_foreach(f, mylist()); 
}