2017-05-12 5 views
2

On C++ weekly ep. 48 by Jason Turner gibt den folgenden Code:Variadische Klassenvorlage und variadische Konstruktor

template<typename ... B> 
struct Merged : B... 
{ 
    template <typename ... T> 
    Merged(T && ... t) : B(std::forward<T>(t))... 
    { } 

    using B::operator()...; 
}; 

Es schlägt mit dem folgenden auf gcc 7.1:

error: mismatched argument pack lengths while expanding 'B' 

Was ist der richtige Weg B zu erweitern?

(BTW, in dem obigen Link scheint der Code mit einigen 7.0 Snapshot zu kompilieren).

Edit1:

Wie @ Jarod42 erwähnt, wird es kompilieren mit Structs als functors wirken. Das eigentliche Video verwendet Lambda und es scheint dort zu brechen.

auto l1 = [] { return 4 ; }; 
auto l2 = [](const int i) { return i * 10; }; 
// This would work, S1, S2 are just functors structs 
Merged<S1, S2> merged1(42, "hello"); 
// This fails 
Merged merged2 = Merged(l1, l2); 

Edit2:

Scheint, wie benutzerdefinierte Abzug Führer funktioniert hier nicht.

Merged merged(l1, l2); 

Aber es funktioniert nicht:

template <typename ... T> 
Merged(T...) -> Merged<std::decay_t<T>...>; 

Die oben sollte folgende Voraussetzungen erfüllt sein können. Es scheint, wie Sie die Typen zu Eingebunden <>

Merged<t1, t2> merged(l1, l2); 

, die wahrscheinlich nicht wirklich, was das Tutorial demonstrieren wollte passieren müssen.

+0

ist das nicht C++ 17 und nicht C++ 11? Zumindest bekomme ich [ganz andere Fehler beim Kompilieren mit C++ 11] (http://ideone.com/Pd4tRO) – user463035818

+2

Ich nehme an, dass Sie dem Konstruktor die falsche Anzahl an Parametern zur Verfügung gestellt haben? – Quentin

+0

Works [hier] (http://coliru.stacked-crooked.com/a/5bdcaec54f760c2). – Jarod42

Antwort

1

Mit

template <typename ... T> 
Merged(T&& ... t) : B(std::forward<T>(t))... 
{} 

sizeof...(T) sollte sizeof...(B) gleich sein: Sie haben von Base ein Argument zu liefern.

Und dann ist es works.

Wenn Sie nicht gleiche Anzahl von Argumente liefern können, Sie hace Fehler ähnlich:

error: mismatched argument pack lengths while expanding 'B'

+0

OK @ Jarod42. Scheint, als käme das Problem aus dem Lambda-Teil. [this] (https://godbolt.org/g/VFRzV8) funktioniert nicht. Der Link wird dem eigentlichen Code im Video sehr ähnlich sein. – Kobi

+1

Es scheint, dass der automatische Typabzug fehlschlägt, siehe [modifiziertes Beispiel mit Lambda] (https://godbolt.org/g/Nfs4Ph) – Jarod42

+0

Bingo @ Jarod42. Das funktioniert. Vielen Dank! – Kobi

2

Scheint, als ob es keine Notwendigkeit, jede Konstruktor definierte hier zu haben ist, und stattdessen nur C++ 17 Aggregat:

template<typename ... B> 
struct Merged : B... 
{ 
// This is not needed, it would actually render this class 
// to be a non-aggregate one. 
// template <typename ... T> 
// Merged(T && ... t) : B(std::forward<T>(t))... 
// { } 

    using B::operator()...; 
}; 

// C++17 class deduction guidance (user defined) 
template <typename ... T> 
Merged(T...) -> Merged<T...>; 

int main() 
{ 
    auto l1 = [] { return 4 ; }; 
    auto l2 = [](const int i) { return i * 10; }; 
    // Note here, using {} for initializing an aggregate 
    Merged merged{l1, l2}; 
} 

Beachten Sie die C++ 17-Klasse Abzug Benutzerführung definiert, sowie mit {} für ein Aggregat zu initialisieren.

Konstruktor wird nicht benötigt. Wenn wir es hätten, wäre diese Klasse kein Aggregat mehr und die Syntax für die Initialisierung würde aufhören zu arbeiten.