0

問題

スカラーと配列の両方で機能するコピー ファンクター「インターフェイス」を実装します。

CopyFunctor::operator()(T& dest, const T& src);

例として、ソート関数を一般化して、要素の配列と「インライン」配列の配列の両方で動作するようにしたいと考えています。

template <typename T, typename CopyFunctor> sort(T array[]);

int array_of_elements[] = {7, 3, 5, 2};
sort(array_of_elements);
// after sorting: {2, 3, 5, 7}

int array_of_arrays[] = {  3, 1,   2, 4,   7, 6,   5, 8};
// inlined arrays are: {3, 1}, {2, 4}, {7, 6}, {5, 8}
// these 'inlined' arrays are fixed-sized
// after sorting using first element as key: { 2, 4,   3, 1,   5, 8,    7, 6}   
// thus, the second element should be moved with the first element

sort(T array[]) 内で、要素 (または要素のグループ) を位置 i から位置 j にスワップするには、a が要素の配列であるか「インライン配列の配列」であるかに関係なく、まったく同じ方法でファンクターを呼び出すことができます。 ':

template <typename T, typename CopyFunctor> sort(T array[], CopyFunctor copy) {

 // ...

   // swap a[i] and a[j]
   copy(b, a[i]);
   copy(a[i], a[j]);
   copy(a[j], b);

 // ...

 }

ここで、b は、a 内の 1 つの「インライン」配列を保持するのに十分な大きさのスカラーまたは配列です。(この例では、おそらく代わりにスワップ ファンクターが必要ですが、より複雑なユース ケースでは、コピー ファンクターが必要でした。)

仮定

インライン配列の配列が初期化されると、サイズが変更されることはありません。

サンプルコード

#include <cstdio>
#include <cstring>
using namespace std;

template <typename T>
struct ScalarSetter {
    void operator()(T& a, const T& b) const {
        a = b;
    }
};

template <typename T>
struct ArraySetter {
    size_t _n;
    ArraySetter(size_t n) : _n(n) {}
    void operator()(T& a, const T& b) const {
        std::memcpy(&a, &b, sizeof(T)*_n);
    }
};

int main(int argc, char* argv[]) {

    {
      ScalarSetter<float> copy;
      float a = 1.0;
      float b = 2.0;
      copy(a, b);
      printf("a = %f\n", a);
      /* output:
       * a = 2.00000
       */
    }

    {
      size_t n = 3;
      ArraySetter<float> copy(n);
      float c[] = {.1, .2, .3, .4};
      float d[] = {.4, .5, .6, .7};
      copy(c[0], d[0]);
      for (size_t i = 0; i < n+1; ++i) {
        printf("c[%d] = %f\n", i, c[i]);
      }
      /* output:
       * c[0] = 0.400000
       * c[1] = 0.500000
       * c[2] = 0.600000
       * c[3] = 0.400000
       */
    }

    return 0;
}

私は実際に Cuda/C++ を使用しているため、多かれ少なかれインライン配列を使用する必要があります。

上記のサンプル コードは、valgrind メモリ テストをコンパイル、実行、および合格します。しかし、ArraySetter::operator()(...) の入力引数へのポインターを導出するのは少し不快に感じます。

(編集:インライン配列が連続していない場合、コードが壊れると思います...(動的に)割り当てられた配列の連続性に保証はありますか?)

スカラーと配列の両方で動作する一貫したコピー ファンクター「インターフェイス」を実装する別の方法はありますか?

4

0 に答える 0