2016-02-11 10 views
7

メンバ初期化子リストで得られたタプルから複数のメンバを初期化できますか?メンバ初期化子リスト:タプルを返す関数からメンバを2つ初期化

タプルを介して複数の値を返すことで、より一般的になりつつあります。なぜ私は言語の制限以外の理由がないのでしょうか?


これは私が持っているもののためMCVEです:

auto new_foo(std::size_t size) -> std::tuple<std::unique_ptr<char[]>, int*> 
{ 
    auto buffer = std::make_unique<char[]>(size * sizeof(int) + 8); 
    auto begin = static_cast<int*>(static_cast<void*>(buffer.get() + 4)); 
    return std::make_tuple(std::move(buffer), begin); 
} 

struct X { 
    std::unique_ptr<char[]> buffer_{nullptr}; 
    int* begin_{nullptr}; 
    std::size_t size_{0}; 

    X(std::size_t size) : size_{size} 
    { 
     std::tie(buffer_, begin_) = new_foo(size); 
    } 
}; 

は、これは

X(std::size_t size) 
     : buffer_{ ??? }, 
      begin_{ ??? }, 
      size_{size} 
    { 
    } 

?:行うことができます、それは返すように私は単純に(各メンバーの初期化のために一度new_fooを呼び出すことはできませんすべての呼び出しで別のタプル)。だから、

X(std::size_t size) 
     : buffer_{std:get<0>(new_foo(size)}, 
      begin_{std:get<1>(new_foo(size)}, 
      size_{size} 
    { 
    } 

それは私が考えた別の解決策としてメンバーを保持することでした(それは、これは同じ結果が最適ではない得るために複数回を呼び出して、そうではなかったとしても)

ことはできませんタプル。私は、クラス内の適切な名前の2人のメンバーが必要であり、get<0>get<1>でアクセスする必要はないので、それを破棄しました。

もう1つの回避策は、2つのメンバーを保持する単純な別の構造を作成することです。この方法では名前を持つことになりますが、別のレベルの修飾子を追加することができます(unique_ptrのため)可能な限りコピー用のコピーを作成する必要があります。


hereC++1zがこれを可能にします構造化されたバインディング(D0144R0)があります報告されているように:私は完全な紙が見つからなかったとして

auto {x,y,z} = f(); 

を、これが役立つならば、私が言うことができませんメンバー初期化リストの文脈で。私はそうは思わない。

答えて

14

タプルを受け取り、それを委譲する別の(場合によってはプライベートの)コンストラクタを定義します。

private: 
    X(std::tuple<std::unique_ptr<char>, int*> t, std::size_t size) 
      : buffer_{std::move(std:get<0>(t))}, 
       begin_{std:get<1>(t)}, 
       size_{size} 
    { } 

public: 
    X(std::size_t size) : X{new_foo(size), size} 
    { } 
関連する問題