1

(D'une certaine façon lié à cette question précédente)C++ variadique expansion pack de modèle par des groupes de taille arbitraire

Je veux évaluer les paramètres d'une fonction de modèle par des groupes de N paramètres. Quelque chose comme ceci:

template <size_t N, typename ... Ts> 
void evaluate(Ts const & ... fn) 
{ 
    for(int i=0; i<2; i++) 
     runH<N>::func(i, fn...); 
} 
int main() 
{ 
    run<3>(// N = 2 
     [](int i){ cout << "lambda func 1: " << std::to_string(i) << endl; }, 
     [](int i){ cout << "lambda func 2: " << std::to_string(i) << endl; }, 
     [](int i){ cout << "lambda func 3: " << std::to_string(i) << endl; }, 
     [](int i){ cout << "lambda func 4: " << std::to_string(i) << endl; }, 
     [](int i){ cout << "lambda func 5: " << std::to_string(i) << endl; } 
    ); 
} 

devrait sortie:

lambda func 1: 0 
lambda func 2: 0 
lambda func 1: 1 
lambda func 2: 1 
lambda func 3: 0 
lambda func 4: 0 
lambda func 3: 1 
lambda func 4: 1 
lambda func 5: 0 
lambda func 5: 1 

doit être manipulé Remainder correctement. Jusqu'à présent, je réussi à évaluer que le premier groupe de paramètres N avec ceci:

template <std::size_t N> 
struct runH 
{ 
    template <typename T0, typename ... Ts> 
    static void func (const int i, T0 const & f0, Ts const & ... fn) 
    { 
     f0(i); 
     runH<N-1U>::func(i, fn...); 
    } 
}; 

template <> 
struct runH<0> 
{ 
    template <typename ... Ts> 
    static void func (const int i, Ts const & ... fn) { } 
}; 

template <size_t N, typename ... Ts> 
void evaluate(Ts const & ... fn) 
{ 
    for(int i=0; i<2; i++) 
     runH<N>::func(i, fn...); 
} 

template <std::size_t N, typename ... Ts> 
void run (Ts const & ... fn) 
{ 
    using unused = int[]; 
    (void)unused { 0, (evaluate<N>(fn...), 0) }; 
} 

Est-il possible pour la fonction run continuer à élargir les paramètres? J'ai essayé d'ajouter une autre ellipse à la fin mais elle ne compile pas.

Répondre

1

Je propose la définition d'un runSkip struct

template <std::size_t N, std::size_t I> 
struct runSkip 
{ 
    template <typename T0, typename ... Ts> 
    static void func (T0 const &, Ts const & ... fn) 
    { runSkip<N, I-1U>::func(fn...); } 

    static void func() 
    { } 
}; 

template <std::size_t N> 
struct runSkip<N, 0U> 
{ 
    template <typename ... Ts> 
    static void func (Ts const & ... fn) 
    { run<N>(fn...); } 
}; 

si run() deviennent

template <std::size_t N, typename ... Ts> 
void run (Ts const & ... fn) 
{ 
    using unused = int[]; 

    std::size_t j; 

    for (auto i = 0 ; i < 2 ; ++i) 
    { 
     j = 0U; 

     (void)unused { 0, ((++j <= N ? ((void)fn(i), 0) : 0), 0)... }; 
    } 

    runSkip<N, N>::func(fn...); 
} 

Ce qui suit est un exemple de travail complet

#include <iostream> 

template <std::size_t, typename ... Ts> 
void run (Ts const & ...); 

template <std::size_t N, std::size_t I> 
struct runSkip 
{ 
    template <typename T0, typename ... Ts> 
    static void func (T0 const &, Ts const & ... fn) 
    { runSkip<N, I-1U>::func(fn...); } 

    static void func() 
    { } 
}; 

template <std::size_t N> 
struct runSkip<N, 0U> 
{ 
    template <typename ... Ts> 
    static void func (Ts const & ... fn) 
    { run<N>(fn...); } 
}; 

template <std::size_t N, typename ... Ts> 
void run (Ts const & ... fn) 
{ 
    using unused = int[]; 

    std::size_t j; 

    for (auto i = 0 ; i < 2 ; ++i) 
    { 
     j = 0U; 

     (void)unused { 0, ((++j <= N ? ((void)fn(i), 0) : 0), 0)... }; 
    } 

    runSkip<N, N>::func(fn...); 
} 

int main() 
{ 
    run<2>(// N = 2 
     [](int i){ std::cout << "lambda func 1: " << i << std::endl; }, 
     [](int i){ std::cout << "lambda func 2: " << i << std::endl; }, 
     [](int i){ std::cout << "lambda func 3: " << i << std::endl; }, 
     [](int i){ std::cout << "lambda func 4: " << i << std::endl; }, 
     [](int i){ std::cout << "lambda func 5: " << i << std::endl; }, 
     [](int i){ std::cout << "lambda func 6: " << i << std::endl; } 
    ); 
} 

Ps: il n'y a pas besoin de std::to_string pour envoyer un entier à une strie de sortie m opérateur.