2016-07-08 23 views
1

4次元の2倍配列を模倣するためにテンプレート構造を使用する場合、各次元の最大サイズはコンパイル時にわかります。したがって、私はテンプレート構造を使用するとパフォーマンスを得るチャンスを与えると思います。あなたは実装のための私の試みを見つけることができます。 1つの構造体をインスタンス化しようとしない限り、コードはコンパイルされます。私はコードの問題が何であるか分からない、提案は非常に感謝されます。C++の効率的なテンプレート構造

さらに、私は可能な限り2つの改善をしたいと思います:1)float型とdouble型のデータを使用できるようにしたい2)値を代入できる何らかのオーバーロードされた演算子T.assign(N、L、M、J、value)を使用する必要がある代わりに、T(N、L、M、J)= valと同様の方法でデータレコードに追加します。再度、提案は非常に高く評価されます。

私の目的は、できるだけ早くT_4Dのデータを埋めることです。

#include <iostream> 
#include <cstring> // for memset                                                    
using namespace std; 

template <size_t dim_N=3,size_t dim_L=3,size_t dim_M=3,size_t dim_J=10,double *data=NULL> 
struct T_4D { 

    enum {SIZE = dim_N*dim_L*dim_M*dim_J }; 
    enum {LEN1 = dim_N }; 
    enum {LEN2 = dim_L }; 
    enum {LEN3 = dim_M }; 
    enum {LEN4 = dim_J }; 



    static void create() 
    { 
    data=(double *)malloc(SIZE*sizeof(double)); 
    memset(data, 0.0, SIZE*sizeof(*data)); 
    } 

    static size_t multi_index(const size_t N) { 
    return N; 
    } 
    static size_t multi_index(const size_t N,const size_t L) { 
    return L*dim_N + N; 
    } 
    static size_t multi_index(const size_t N,const size_t L, const size_t M) { 
    return (M*dim_L + L)*dim_N + N; 
    } 
    static size_t multi_index(const size_t N,const size_t L, const size_t M,const size_t J) { 
    return ((J*dim_M + M)*dim_L + L)*dim_N + N; 
    } 

    double operator()(size_t N,size_t L, size_t M, size_t J){ 
    return data[multi_index(N,L,M,J)]; 
    } 

    static void assign(size_t N,size_t L, size_t M, size_t J,double value){ 
    data[multi_index(N,L,M,J)]=value; 
    } 


}; 

int main() 
{ 
    double *instance; 
    T_4D<3,3,3,10,instance> T; 
    T.create(); 

    return 0; 
} 

コンパイルエラーは以下のとおりです。テンプレートパラメータとしてdouble* data = NULLを使用して

./main.cpp: In function ‘int main()’: 
./main.cpp:49:17: error: the value of ‘instance’ is not usable in a constant expression 
    T_4D<3,3,3,10,instance> T; 
       ^
./main.cpp:48:11: note: ‘instance’ was not declared ‘constexpr’ 
    double *instance; 
     ^
./main.cpp:49:25: error: ‘instance’ is not a valid template argument because ‘instance’ is a variable, not the address of a variable 
    T_4D<3,3,3,10,instance> T; 
         ^
./main.cpp:50:5: error: request for member ‘create’ in ‘T’, which is of non-class type ‘int’ 
    T.create(); 
    ^
Makefile:197: recipe for target 'obj/main.o' failed 
make: *** [obj/main.o] Error 1 
+0

エラーは何ですか? – pingul

+1

実行時に決定されたもの( 'instance')をコンパイル時に決定されたテンプレートにバインドしようとすると、エラーが発生します。なぜオブジェクト内の値にポインタを格納しないのですか? – pingul

+1

それに加えて、テンプレートパラメータの値を再割当てすることはできないので、 'create'呼び出しはそのまま動作することができません。 – zneak

答えて

1

ディメンションのすべてがコンパイル時に知られている場合は、動的なメモリを割り当てるための必要はありません。単に:

std::aligned_storage_t<sizeof(T) * SIZE, alignof(T)> data; 

PODタイプを扱っているので、何も初期化する必要はありません。あなたはメモリをゼロにしたい場合は、ちょうどこの使用:我々は、静的連続したメモリを使用するので

for (std::size_t i = 0; i < SIZE; ++i) 
    *(reinterpret_cast<T*>(&data) + i) = 0; 

をこれは、最も効率的な実装になります。適切なインデックス作成を実装する必要がありますが、あまり難しくありません。

実際には、​​またはstd::array<T, SIZE> dataを使用してください。

また、double*テンプレートパラメータを削除しても変更できないため、データに使用することはできません。

+0

初期化を実装してくれてありがとう、私はreste関数を追加しましたが、 "./main.cpp:19:39:error:タイプ 'std :: aligned_storage <2160ul, 8ul>'から 'double * *(reinterpret_cast (data)+ i)= 0; " –

+0

@RubénDaríoGuerreroには '&'がありませんでした。一定。私の悪い、私は私の電話から答えています。 '_t'バージョンを使うことを忘れないでください。 'typename std :: aligned_storage :: type'を使用してください。 – user2296177

+0

問題が解決しました。もう1つの詳細:データに値を割り当てようとすると、エラーが発生します。 "./main.cpp:119:14:error: 'T.T_4D :: data'のメンバー 'assign'を要求します。 -class type 'std :: aligned_storage <8ul, 8ul> :: type [270]' T.data.assign(N、L、M、J、0.1); "何か案が? –

1

はないと思えます。

data=(double *)malloc(SIZE*sizeof(double)); 

あなたはテンプレートパラメータとしてこれを削除し、そのクラスのメンバ変数にすることができます:あなたがやっているのようにして、テンプレートパラメータとしてdouble*を使用することができますが、それに割り当てることができません。

template <size_t dim_N=3,size_t dim_L=3,size_t dim_M=3,size_t dim_J=10> 
struct T_4D { 

    double* data; 

    ... 

メンバー関数ではなく、コンストラクタでメモリを割り当てます。

T_4D() : data(new double[SIZE]) 
{ 
    memset(data, 0.0, SIZE*sizeof(*data)); 
} 

あなたは、ヒープからメモリを割り当てているので、The Rule of ThreeThe Rule of Fiveに従うことを忘れないでください。

その後、mainは単純になります

int main() 
{ 
    T_4D<3,3,3,10> T; 
    return 0; 
} 
関連する問題