2015-09-02 3 views
5

Ich versuche, eine Möglichkeit zu erstellen, mehrere Parameterpakete direkt zu erweitern. Ich habe eine Funktion template<size_t X,typename F> auto sequenceFunc(F&& f) erstellt, die eine gegebene Funktion f mit einem erweiterten integer_sequence aufruft.C++: Erweiterung des Parameterpakets in Lambda schlägt fehl

Das funktioniert gut für kleine Funktionen wie folgt aus:

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] 
    }); 
} 

Leider erweitern Ich kann nicht mehrere Parameter Packs, auch wenn ich die Regel folgen, dass nur ein Parameter Pack ... -Ausdrucks in einem sein kann. Dies ist mein Versuch, diese Funktion für die Matrixmultiplikation bei Verwendung:

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 
     }; 
    }); 
} 

Dies ist der Fehler:

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

Ich verstehe nicht wirklich, warum eine Erweiterung notwendig ist, weil es eine andere ist ... außerhalb der Ausdruck. Ich benutze GCC 5.1.0.

Informationenvec und mat sind nur using -declarations für std::array und eine verschachtelte std::array<std::array<A,T>,B>

+5

GCC hat Probleme mit Packs in Lambdas. –

+0

@ T.C. Bugzilla-Link? – Mgetz

Antwort

4

Diese gcc bug 47226 ist. Es ist immer noch offen, und das Codebeispiel schlägt immer noch auf gcc 5.2.0 fehl, während es beim clang 3.6 gut kompiliert. Ihr Code sieht für mich korrekt aus.

+0

Das ist ein schrecklicher 'print_all'? Es druckt * nicht in der Reihenfolge *. – Yakk

+0

@Yakk Hm. Ich mache klar, wie man das mit dem Lambda macht. Gibt es dafür keinen Weg? – Barry

+0

'Vorlage void do_each (F && ... f) {(void) int [] {0, (std :: vorwärts (f)(), void(), 0) ...}; } ', dann' do_each ([&] {std :: cout << t << '\ n';} ...); 'in' print_all'. Lambda wird verwendet, um Aufgaben zu paketieren, Initialisierungsliste wird verwendet, um sie in der Reihenfolge auszuführen. Wenn Sie "do_each" nicht als Lambda schreiben (einfach, aber warum?), Sehen Sie nicht, wie Sie die Erweiterung "als Lambda" ausführen können. – Yakk

0

Ich habe gerade das gleiche Problem festgestellt. Ich fand keinen besseren Betrogenen und wollte keine neue Frage aufwerfen, möchte aber meine Ergebnisse teilen. In einem Kommentar zu einer ähnlichen Frage habe ich einen Workaround gefunden, der die Parameter in ein Tupel packt und dann innerhalb des Lambda entpackt (den Link finde ich leider nicht mehr). Diese Lösung erfordert jedoch C++ 17 (std::apply und mehr).

Mein Fall war so etwas wie diese:

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

die nicht mit gcc 4.8.5 arbeiten. Zu meiner Überraschung, das Schreiben aus einfach explizit das Lambda als Funktors wie ein Zauber funktioniert:

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...>(); 
    } 
}; 

ich es ein bisschen seltsam, dass gcc schlucken diese, die zwar nicht die erste. Afaik Lambdas sind nur syntaktischer Zucker für anonyme Funktoren auf Funktionsumfang. Wahrscheinlich ist mein Wissen über Compiler einfach zu wenig, um zu verstehen, was das Problem bei der Behebung dieses Fehlers ist.

Verwandte Themen