簡體   English   中英

傳遞std :: array作為模板可變參數的參數

[英]Passing std::array as arguments of template variadic function

我正在嘗試學習C ++ 11中的可變參數模板。 我有一個基本上是std::array的包裝器的類。 我希望能夠將函數對象(最好是lambdas)傳遞給成員函數,然后將std::array的元素作為函數對象的參數傳遞。

我已經使用static_assert來檢查參數的數量是否與數組的長度匹配,但是我無法想到一種將元素作為參數傳遞的方法。

這是代碼

#include <iostream>
#include <array>
#include <memory>
#include <initializer_list>

using namespace std;

template<int N, typename T>
struct Container {
    template<typename... Ts>
    Container(Ts&&... vs) : data{{std::forward<Ts>(vs)...}} {
        static_assert(sizeof...(Ts)==N,"Not enough args supplied!");
    }

    template< typename... Ts>
    void doOperation( std::function<void(Ts...)>&& func )
    {
        static_assert(sizeof...(Ts)==N,"Size of variadic template args does not match array length");

        // how can one call func with the entries
        // of data as the parameters (in a way generic with N)
    }

    std::array<T,N> data;
};

int main(void)
{
    Container<3,int> cont(1,2,3);

    double sum = 0.0;
    auto func = [&sum](int x, int y, int z)->void{
        sum += x;
        sum += y;
        sum += z;
    };

    cont.doOperation(std::function<void(int,int,int)>(func));

    cout << sum << endl;

    return 0;
}

所以我的問題(如代碼所示)是如何以一種與N通用的方式將data條目傳遞到函數func上?

額外的問題:是否有可能避免將main的std::function難看地轉換為main並直接傳遞一個lambda?

鑒於著名的索引基礎架構:

namespace detail
{
    template<int... Is>
    struct seq { };

    template<int N, int... Is>
    struct gen_seq : gen_seq<N - 1, N - 1, Is...> { };

    template<int... Is>
    struct gen_seq<0, Is...> : seq<Is...> { };
}

您可以通過以下方式重新定義類模板:

template<int N, typename T>
struct Container {
    template<typename... Ts>
    Container(Ts&&... vs) : data{{std::forward<Ts>(vs)...}} {
        static_assert(sizeof...(Ts)==N,"Not enough args supplied!");
    }

    template<typename F>
    void doOperation(F&& func)
    {
        doOperation(std::forward<F>(func), detail::gen_seq<N>());
    }

    template<typename F, int... Is>
    void doOperation(F&& func, detail::seq<Is...>)
    {
        (std::forward<F>(func))(data[Is]...);
    }

    std::array<T,N> data;
};

這是一個生動的例子

請注意,您不需要在main()構造std::function對象:可以從lambda隱式構造std::function 但是,您甚至根本不需要在這里使用std::function ,這可能會導致不必要的運行時開銷。

在上面的解決方案中,我只是將可調用對象的類型設為可以由編譯器推導的模板參數。

您可以使用此實用程序模板在編譯時創建索引序列:

template< std::size_t... Ns >
struct indices {
    typedef indices< Ns..., sizeof...( Ns ) > next;
};

template< std::size_t N >
struct make_indices {
    typedef typename make_indices< N - 1 >::type::next type;
};

template<>
struct make_indices< 0 > {
    typedef indices<> type;
};

然后,創建一個將indices作為參數的調用程序函數,以便您推斷出索引序列:

template<typename... Ts, size_t...Is>
void call(std::function<void(Ts...)>&& func, indices<Is...>)
{
    func( data[Is]... );
}

然后您可以這樣稱呼它:

template< typename... Ts>
void doOperation( std::function<void(Ts...)>&& func )
{
    static_assert(sizeof...(Ts)==N,"Size of variadic template args does not match array length");
    call( std::forward<std::function<void(Ts...)>>(func), typename  make_indices<N>::type() );
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM