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

私がここでやろうとしているのは、3つの異なる方法でこの同じ値を扱う3つの異なるクラスがあるということです。ここで得られる問題は、パラメータパックを拡張し、与えられた単一の値を持つ各クラスを初期化する方法です。なぜvariadicテンプレートのパラメータパックが展開されていないのですか?

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

私は、コンパイラはこれを好きではないように上記のコードは

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

ルックスに展開されるだろうと思うだろう。 ただし、以下のすべてのコードがちょうど

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

罰金をコンパイルするだろう、私はArgsの(A)...を展開して失敗した理由を知りたいですか? Args(a)...とArgs {a} ...の違いは何ですか?どのようにstd :: forward(a)...)?

私はGNU 4.7.1

+3

曖昧さを? 'tuple argstuple3((Args(a))...);)を試しましたか? (注:名前も変更されていますが、それは以前のdeclと競合します)。 – WhozCraig

+0

@WhozCraigあなたは絶対に正しいです、(Args(a))...それを修正します。あなたは少し精巧にできますか?ここではあいまいさは何ですか?どうもありがとう。 – codeinc

+3

ほとんどのVexing解析: – Quentin

答えて

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

を使用しています打ち鳴らすには、より優れたエラーコードがあります

<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は聞き覚えがなければなりません。 これは関数宣言と見なされます。

このargstuple3は、ファンクション名のように見え、タプル<>を返し、引数Args(a)を持ちます。

このArgsの(A)は、「Argsの」(タイプ)と渡されている「」

コンパイラはあなたが与える場合は、この

tuple<int> argtuple3(int()); 

のようなものとして、それを見ることができますを返す関数ポインタとして見られている

試してみると、同じ正確なエラーが表示されます。

この解決するための別のオプション:

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

"このArgs(a)は 'Args'(型)を返し、 'a'" Nopeを返す関数ポインタと見なされます。 –

+1

@ T.C。コンパイラがこの "Arg(a)"関数ポインタを見ないと言っていますか? – Kobi

+1

@ Kobi私はvexing-parseを読んだ後、コンパイラはArg(a)と同じように見えると思います。つまり、変数 "a"にはArgがあります。 (Args ...) – codeinc

関連する問題