可変個引数テンプレートから引数を読み取る

最初の N を消費する関数のオーバーライドを提供する必要があります (通常は 1 つの) 引数。

void foo() {
   // end condition argument pack is empty
}

template <class First, class... Rest> 
void foo(First first, Rest... rest) {
    // Do something with first
    cout << first << endl; 

    foo(rest...); // Unpack the arguments for further treatment
}

可変個引数をアンパックすると、次のオーバーロードが検出されます。

例:

foo(42, true, 'a', "hello");
// Calls foo with First = int, and Rest = { bool, char, char* }
// foo(42, Rest = {true, 'a', "hello"}); // not the real syntax

次に、次のレベルで前の Rest を展開します そして取得:

foo(true, Rest = { 'a', "hello"}); // First = bool

Rest まで続きます メンバーが含まれていない場合、アンパックすると foo() が呼び出されます (引数のないオーバーロード)。

種類が異なる場合のパックの保管

引数パック全体を保存したい場合は、 std::tuple を使用できます

template <class... Pack>
void store_pack(Pack... p) {
    std::tuple<Pack...> store( p... );
    // do something with store
}

ただし、これはあまり役に立たないようです。

均質な場合のパックの保管

パック内のすべての値が同じ型の場合、次のようにすべて保存できます:

vector<int> reverse(int i) {
    vector<int> ret;
    ret.push_back(i);
    return ret;
}

template <class... R>
vector<int> reverse(int i, R... r) {
    vector<int> ret = reverse(r...);
    ret.push_back(i);
    return ret; 
}

int main() {
    auto v = reverse(1, 2, 3, 4);
    for_each(v.cbegin(), v.cend(), 
        [](int i ) { 
            std::cout << i << std::endl; 
        }
    );
}

ただし、これはさらに少ないようです


引数がすべて同じ型の場合、次のように引数を配列に格納できます (配列の最初の引数の型を使用):

template <class T, class ...Args>
void foo(const T& first, const Args&... args)
{
    T arr[sizeof...(args) + 1] = { first, args...};
}

int main()
{
    foo(1);
    foo(1, 10, 100, 1000);
}

型が違うなら boost::any でいいと思います しかし、指定されたテンプレートの外で、どのアイテムがどのタイプのものか (格納された値をどのように使用するか) をどのように調べるのかわかりません。

編集: 引数がすべて同じ型であり、それらを STL コンテナーに格納する場合は、代わりに std::initializer_list<T> を使用できます .たとえば、値を逆に格納する Motti の例:

#include <vector>
#include <iostream>
#include <iterator>

template <class Iter>
std::reverse_iterator<Iter> make_reverse_iterator(Iter it)
{
    return std::reverse_iterator<Iter>(it);
}

template <class T>
std::vector<T> reverse(std::initializer_list<T> const & init)
{

    return std::vector<T>(make_reverse_iterator(init.end()), make_reverse_iterator(init.begin()));
}

int main() {
    auto v = reverse({1, 2, 3, 4});
    for (auto it = v.begin(); it != v.end(); ++it) {
        std::cout << *it << std::endl;
    }
} 

引数の型が異なる場合に配列に固執するには、 std::common_type<> も使用できます

template<class ...A> void func(A ...args){
   typedef typename std::common_type<A...>::type common;
   std::array<common, sizeof...(A)> a = {{ args... }};
}

たとえば、func(std::string("Hello"), "folks") std::string の配列を作成します .