2017-05-18 3 views
3
#include<tuple> 
#include<iostream> 
using namespace std; 

class A                                       
{                                         
public:                                       
    int v;                                       
    A(int a) : v(a){}                                    
    operator int(){return v;}                                  
};                                         

class B                                       
{                                         
public:                                       
    int v;                                       
    B(int a) : v(a + 1) {}                                    
    operator int(){return v;}                                  
};                                         

class C                                       
{                                         
public:                                       
    int v;                                       
    C(int a) : v(a + 2){}                                    
    operator int(){return v;}                                  
};                                         


template <typename... Args >                                  
int f(int a, Args... args)                                  
{                                         
    tuple<Args...> argstuple1(std::forward<Args>(a)...);                           
    tuple<Args...> argstuple2(Args{a}...);                               
    //The following initialization won't compile 
    tuple<Args...> argstuple2(Args(a)...); 

    cout << (int)std::get<2>(argstuple2) << endl;                             
    return 1;                                      
} 

int main() 
{ 
    f< A, B, C>(5,0,0,0); 
} 

Was ich hier zu tun versuche, ist, gegeben einen Wert, habe ich 3 verschiedene Klassen, um diesen gleichen Wert auf 3 verschiedene Arten zu behandeln. Das Problem, das ich hier bekommen habe, ist, wie man die Parameterpakete erweitert und jede Klasse mit dem gegebenen Einzelwert a initialisiert.Warum variadic Template-Parameterpakete nicht erweitert?

tuple<Args...> argstuple2(Args(a)...); 

Ich würde denken, der obige Code würde in

tuple<A, B, C> argstuple2(A(a), B(a), C(a)); 

erweitert werden Sieht aus wie der Compiler dies nicht mag. Allerdings alle folgenden Codes würde ganz gut kompilieren

tuple<Args...> argstuple2(Args(1)...); 
tuple<Args...> argstuple2(Args{a}...); 
tuple<Args...> argstuple2(std::forward<Args>(a)...);     

Ich mag würde wissen, warum Args (a) ... nicht erweitern? Was ist der Unterschied zwischen Arg (a) ... und Arg (a) ...? Wie wäre es mit std :: forward (a) ...)?

Ich bin mit Gnu 4.7.1

+3

Mehrdeutigkeit? Hast du 'tuple argstuple3 ((Args (a)) ...);'? (Hinweis: änderte auch den Namen; es widerspricht der vorherigen Deklaration). – WhozCraig

+0

@WhozCraig Sie haben absolut Recht, (Args (a)) ... behebt es. Können Sie ein wenig näher erläutern, was ist die Mehrdeutigkeit hier? Danke vielmals. – codeinc

+3

Most Vexing Parse :) – Quentin

Antwort

2
// now it will 
using tuple_args = tuple<Args...>;                                         
tuple_args argstuple3((Args(a))...); 
-1

Klirren eine bessere Fehlercode:

<source>:36:28: warning: parentheses were disambiguated as a function 
declaration [-Wvexing-parse] 
    tuple<Args...> argstuple3(Args(a)...); 
          ^~~~~~~~~~~~ 
<source>:36:29: note: add a pair of parentheses to declare a variable 
    tuple<Args...> argstuple3(Args(a)...); 
          ^
          ( ) 

vexing-parse vertraut klingen sollte. Es wird als eine Funktionsdeklaration gesehen.

Dieses argstuple3 sieht wie ein Funktionsname aus, der ein Tupel <> zurückgibt und Argumente Args (a) hat.

Diese Args (a) als Funktionszeiger gesehen, dass 'a'

geben kehrt 'Args' (Typ) und wird

Compiler wird es als so etwas wie dieses

tuple<int> argtuple3(int()); 

sehen Wenn Sie geben Es ist ein Versuch, Sie werden den gleichen genauen Fehler sehen.

Eine weitere Möglichkeit dieses Problem zu lösen:

tuple<Args...> argstuple3{Args(a)...}; 
+0

"Diese Args (a) wird als Funktionszeiger, der 'Args' (Typ) zurückgibt und als 'a'" Nein. –

+1

@ T.C. sagen Sie, der Compiler würde diesen "Arg (a)" keinen Funktionszeiger sehen? – Kobi

+1

@Kobi Nach dem Lesen von Vexing-Parse, ich denke, der Compiler würde sehen, Arg (a) wie "Arga", mit anderen Worten, Variable "a" hat den Typ Arg, so wird argstuple2 eine Funktion Erklärung etwas wie Tupel argstuple (Arg ...) – codeinc

Verwandte Themen