29

見つけられなかったので、すでに回答されていたらすみません...

基本的に、コンストラクターで可変引数リストを取得し、引数をベクトルに格納する必要があるオブジェクトがあります。可変引数コンストラクタの引数からベクトルを初期化するにはどうすればよいですか?

class GenericNode {
public:
    GenericNode(GenericNode*... inputs) {
            /* Something like... */
        // inputs_.push_back(inputs)...;
}
private:
    std::vector<GenericNode*> inputs_;
};
4

6 に答える 6

29

最良の方法は、初期化子リストを使用することです

#include <initializer_list>
#include <vector>
class GenericNode {
public:
    GenericNode(std::initializer_list<GenericNode*> inputs) 
        :inputs_(inputs) {} //well that's easy
private:
    std::vector<GenericNode*> inputs_;
};
int main() {
    GenericNode* ptr;
    GenericNode node{ptr, ptr, ptr, ptr};
} //compilation at http://stacked-crooked.com/view?id=88ebac6a4490915fc4bc608765ba2b6c

C++ 11 を使用して既に持っているものに最も近いのは、ベクトルの initializer_list を使用することです。

    template<class ...Ts>
    GenericNode(Ts... inputs) 
        :inputs_{inputs...} {} //well that's easy too
    //compilation at http://stacked-crooked.com/view?id=2f7514b33401c51d33677bbff358f8ae

そして、これはinitializer_listsがまったくないC++ 11バージョンです。これは見苦しく、複雑で、多くのコンパイラに欠けている機能が必要です。初期化子リストを使用する

template<class T>
using Alias = T;

class GenericNode {
public:
    template<class ...Ts>
    GenericNode(Ts... inputs) { //SFINAE might be appropriate
         using ptr = GenericNode*;
         Alias<char[]>{( //first part of magic unpacker
             inputs_.push_back(ptr(inputs))
             ,'0')...,'0'}; //second part of magic unpacker
    }
private:
    std::vector<GenericNode*> inputs_;
};
int main() {
    GenericNode* ptr;
    GenericNode node(ptr, ptr, ptr, ptr);
} //compilation at http://stacked-crooked.com/view?id=57c533692166fb222adf5f837891e1f9
//thanks to R. Martinho Fernandes for helping me get it to compile

すべてとは関係ありませんが、それらがポインターを所有しているかどうかはわかりません。std::unique_ptrそうである場合は、代わりに使用してください。

于 2012-12-20T20:11:33.997 に答える
9
    // inputs_.push_back(inputs)...;

関数の引数リストや初期化リストなどの特定のコンテキストでのみ、パラメーターパックをステートメントとして展開できないため、これは機能しません。

また、コンストラクターの署名が間違っています。可変引数テンプレートを作成しようとしている場合は、テンプレートである必要があります!

コンストラクターの署名を正しく記述したら、答えは簡単です。パック展開を使用してベクターを構築するだけです。

#include <vector>

class GenericNode
{
public:
  template<typename... T>
    GenericNode(T*... inputs) : inputs_{ inputs... }
    { }
private:
    std::vector<GenericNode*> inputs_;
};

(代わりに、コンストラクター本体で次のように設定することもできます。

inputs_ = { inputs... };

しかし、クールな子供たちは、コンストラクター本体で代入ではなくメンバー初期化子を使用します。)

このソリューションの欠点は、テンプレート コンストラクターが任意の型のポインター引数を受け入れることですが、引数が に変換できない場合、ベクトルを作成しようとするとエラーが発生することGenericNode*です。ポインターのみを受け入れるようにテンプレートを制限することもできますが、他の回答が示唆することをGenericNode行い、コンストラクターに.std::initializer_list<GenericNode*>enable_if

于 2012-12-20T20:55:14.753 に答える
3

テンプレートでない限り、可変引数リストを使用することはできません。前述のように、次のように initializer_list を使用できます。

class GenericNode {
public:
    GenericNode(std::initializer_list<GenericNode*> inputs) : inputs_(inputs)
    {
    }
private:
    std::vector<GenericNode*> inputs_;
};

template <class ... T>
GenericNode* foo(T ... t)
{
    return new GenericNode({t...});
}
于 2012-12-20T20:06:42.537 に答える
2
class Blob
 {
    std::vector<std::string> _v;
 public:

    template<typename... Args>
    Blob(Args&&... args)
    : _v(std::forward<Args>(args)...)
    {  }

};

int main(void)
{
    const char * shapes[3] = { "Circle", "Triangle", "Square" };

    Blob b1(5, "C++ Truths"); 
    Blob b2(shapes, shapes+3);
}

C++11 Truths の例は十分に単純に見えます...;) 完全な解決策ではありませんが、いくつかのアイデアが得られるかもしれません。

于 2013-10-29T02:11:03.210 に答える
1

それを行う別の方法:

#include <iostream>
#include <vector>

using std::vector;

template <typename T>
void variadic_vector_emplace(vector<T>&) {}

template <typename T, typename First, typename... Args>
void variadic_vector_emplace(vector<T>& v, First&& first, Args&&... args)
{
    v.emplace_back(std::forward<First>(first));
    variadic_vector_emplace(v, std::forward<Args>(args)...);
}

struct my_struct
{
    template <typename... Args>
    my_struct(Args&&... args)
    {
        variadic_vector_emplace(_data, std::forward<Args>(args)...);
    }

    vector<int>& data() { return _data; }

private:
  vector<int> _data;
};


int main()
{
    my_struct my(5, 6, 7, 8);

    for(int i : my.data())
      std::cout << i << std::endl;
}
于 2012-12-21T00:18:54.950 に答える