2015-09-02 11 views
5

Sto tentando di creare un modo per espandere direttamente più pacchetti di parametri. Ho creato una funzione template<size_t X,typename F> auto sequenceFunc(F&& f), che chiama una determinata funzione f con un integer_sequence espanso.C++: espansione del pacco di parametri all'interno del guasto lambda

Questo funziona bene per piccole funzioni in questo modo:

template<typename T, 
     size_t A,size_t B> 
vec<B,T> col(const mat<A,B,T>& a,const size_t& i){ 
    return sequenceFunc<A>([&](auto... J) -> vec<B,T>{ 
     return { a[J][i]... }; //expands to a[0][i], a[1][i], ... a[A-1][i] 
    }); 
} 

Purtroppo non può espandersi confezioni multiple di parametri, anche se seguo la regola, che solo un parametro pack può essere all'interno di un ... -expression. Questo è il mio tentativo di utilizzare questa funzione per la moltiplicazione tra matrici:

template<typename S,typename T, 
     size_t A,size_t B,size_t C> 
mat<C,B,S> mul(const mat<A,B,S>& a,const mat<C,A,T>& b){ 
    return sequenceFunc<B>([&](auto... I)->mat<C,B,S>{ //for all B rows in a... 
     return { 
      sequenceFunc<C>([&](auto... J)->vec<C,S>{ // ... look at all C columns in b and calculate dot product. 
       auto i = I; //putting "I" outside the expansion of "J" 
       return { 
        dot(row(a,i),col(b,J))... //expands J 
       }; 
      })... //expands I 
     }; 
    }); 
} 

Questo è l'errore:

error: parameter packs not expanded with '...': 
     auto i = I; 
      ^

Io non capisco il motivo per cui l'espansione è necessario, perché c'è un altro ... fuori l'espressione. Io uso GCC 5.1.0.

Informazionivec e mat sono solo using -declarations per std::array ed un annidata std::array<std::array<A,T>,B>

+5

GCC ha problemi con i pacchetti in lambda. –

+0

@ T.C. collegamento bugzilla? – Mgetz

risposta

4

Questo è gcc bug 47226. È ancora aperto e l'esempio di codice non riesce ancora su gcc 5.2.0, mentre compila bene su clang 3.6. Il tuo codice sembra corretto per me.

+0

Questo è un 'print_all' orribile? Stampa * fuori uso *. – Yakk

+0

@ Yakk Hm. Mi sto chiaramente nascondendo su come farlo con il lambda allora. Non c'è un modo per farlo? – Barry

+0

'modello void do_each (F && ... f) {(void) int [] {0, (std :: forward (f)(), void(), 0) ...}; } ', quindi' do_each ([&] {std :: cout << t << '\ n';} ...); 'in' print_all'. Lambda è usato per impacchettare le attività, l'elenco di inizializzazione è usato per eseguirle in ordine. Escludendo la scrittura di 'do_each' come lambda (facile, ma perché?), Non vediamo come fare l'espansione" come una lambda ". – Yakk

0

Ho appena incontrato lo stesso problema. Non ho trovato un duplicato migliore e non volevo aprire una nuova domanda, ma voglio comunque condividere le mie scoperte. In un commento a una domanda simile ho trovato una soluzione che mette i parametri in una tupla e poi la decomprime all'interno del lambda (scusa non trovo più il collegamento). Tuttavia, questa soluzione richiede C++ 17 (std::apply e altro).

Il mio caso era qualcosa di simile:

struct Foo{ 
    template <typename T,typename ...ARGS> 
    void foo(T t,ARGS...args){ 
    auto x = [&](){ t(args...);} 
    } 
}; 

che non sta lavorando con gcc 4.8.5. Con mia grande sorpresa, semplicemente scrivendo esplicitamente lambda come functor funziona come un fascino:

template <typename T,typename ...ARGS> 
struct FooFunct{ 
    void operator()(T t,ARGS...args){ 
    t(args...); 
    }  
}; 

struct Foo{ 
    template <typename T,typename ...ARGS> 
    void foo(T t,ARGS...args){ 
    auto x = FooFunct<T,ARGS...>(); 
    } 
}; 

lo trovo un po 'strano, che inghiotte GCC Questo, pur non essendo il primo. I lambda afaik sono solo zucchero sintattico per i funtori anonimi in funzione. Probabilmente la mia conoscenza dei compilatori è troppo piccola per capire qual è il problema nel correggere questo bug.

Problemi correlati