2016-04-03 6 views
1

これはmy previous oneへのフォローアップの質問です。私は基本的なベクトル演算機能を持つArrayクラスを構築しています。私は、ユーザーが配列全体に任意の関数をマップできるようにする関数を定義したいと考えています。私はすでに定義済みのバイナリ関数(インプレース追加の場合はoperator+=)に対してこれを行うことができますが、任意の入力数に対してこれがどのように実行されるのか苦労しています。可変引数の任意の数に関数を適用する

template<typename T, size_t ... Ns> 
class Array 
{ 
public: 
    Array() { /* allocate memory of size product(Ns) * sizeof(T) */ } 

    ~Array() { /* deallocate memory */ } 

    inline Array<T, Ns...>& operator+=(const Array<T, Ns...> &rhs)     
    { 
     // simple case: predefined operation on exactly two Arrays 
     T *p1 = data, *p2 = rhs.data;             
     while (p1 != data + size) { *p1 += *p2; p1++; p2++; }                    
     return *this;                 
    } 

    template<class ... Args> 
    inline const Array<T, Ns...> map(T (*fn)(arg_type<Args>...), Args ... args) 
    { 
     // difficult case: arbitrary operations on a variable number of Arrays 
    } 

    private: 
     T *data; 
     size_t size; 
} 

// example usage 
double f(double a, double b) { return a + b; } 
Array<double,2> x, y, z; 
x.map(f, y, z); 

私は彼らにfを適用し、yz内のすべての要素をループにこのような何かをしたい、とxに格納します。私は私のoperator+=関数でモデル化できると思ったが、私はまだ何か似たような(そしてコンパイル)をさせるパラメータパック展開を見つけていない。この

+0

その中心には、 '(data [I] = f(args [I] ...))...]のようなものがあります。ヘルパー関数のテンプレートでは' index_sequence 'と' Args ... args'とします。 –

+0

は 'data 'は常に1次元です(つまり、' Nsは常に単一の値を含みます)。 –

+0

データとサイズをTのベクトルで置き換えます。N個のベクトルを取り、すべてのベクトルに関数を適用して結果のベクトルを返します。ベクトルをとるarrrayクラスのコンストラクタを記述します。 – Yakk

答えて

0

書き込み:

template<class T, class Array2> 
using Array_Size_Copy = // expression that creates a Array<T,???>, where ??? is the Ns... of Array2 above 

その後、

template<class F, class A0, class...Arrays> 
auto array_apply(F&& f, A0&& a0, Arrays&&...arrays) { 
    using R = decay_t<decltype(f(std::declval<A0>().data.front(), std::declval<Arrays>().data.front()...))>; 

    Array_Size_Copy<R, std::decay_t<A0>> retval; 

    for (int i = 0; i < a0.size(); ++i) { 
    retval.data[i] = f(std::forward<A0>(a0).data[i], std::forward<Arrays>(arrays).data[i]...); 
    } 
    return retval; 
} 

いくつかの追加は、すべてが同じサイズであること(静的が理想的にアサート)をアサートします。

上記の機能は、おそらく友人である必要があります。つまり、autoの代わりに戻り値を設定する必要があるかもしれませんが、それは単に型の体操を宣言に移しているだけです。

関連する問題