c++における自己参照的なクラスに関して

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
efa

c++における自己参照的なクラスに関して

#1

投稿記事 by efa » 7年前

次に示すコードは実行できます。(5回文章が出力されます。)

コード:

#include <iostream>
template <class T> class DimClass{
public:
	DimClass<T>* ptr;
	DimClass(int dim){
		std::cout << "Constructor (" << dim << ")\n";
		if(dim>1) ptr = new DimClass<T>(dim-1);
	}
};

int main(void){
	DimClass<int> test(5);
	return 0;
}
しかし、このDimClassをこう変更するとコンパイルエラーになります。
確かにこのクラスはポインタの自己参照?を行ってはいるのですが、一定の値で止まるようにはなっています。
c++において、このようなことは不可能なのでしょうか。

コード:

template <class T> class DimClass{
public:
	DimClass<T*>* ptr;
	DimClass(int dim){
		std::cout << "Constructor (" << dim << ")\n";
		if(dim>1) ptr = new DimClass<T*>(dim-1);
	}
};
(STLのような配列を実現する際、このように設計してみようと考えました。示しているコードは問題の部分を抜粋しています。)
ご教授お願いします。

YuO
記事: 947
登録日時: 13年前
住所: 東京都世田谷区

Re: c++における自己参照的なクラスに関して

#2

投稿記事 by YuO » 7年前

efa さんが書きました:しかし、このDimClassをこう変更するとコンパイルエラーになります。
確かにこのクラスはポインタの自己参照?を行ってはいるのですが、一定の値で止まるようにはなっています。
c++において、このようなことは不可能なのでしょうか。
メンバ変数で使われているため,newするかどうかに関わらずDimClass<T*>はインスタンス化されます。
このため,コンパイラはDimClass<int>からDimClass<int *>, DimClass<int **>……と無限に作ろうとして,当然ながら限界になってエラーになります。

このような場合は,テンプレートの部分特殊化を使うのが一般的かと思います。

コード:

#include <iostream>

template <typename T, int N> class DimClass{
public:
    DimClass<T *, N - 1> * ptr;
    DimClass() {
        std::cout << "Constructor (" << N << ")\n";
        ptr = new DimClass<T *, N - 1>();
    }
    ~DimClass() { delete ptr; }
};

template <typename T> class DimClass<T, 0> {
public:
    DimClass() {
        std::cout << "Constructor (" << 0 << ")\n";
    }
};

int main(void) {
    DimClass<int, 5> * test = new DimClass<int, 5>();
    delete test;
    return 0;
}

efa

Re: c++における自己参照的なクラスに関して

#3

投稿記事 by efa » 7年前

なるほど…
テンプレートに引数を追加し、部分特殊化をすると可能なんですね。
これでできそうです。有難うございます!

閉鎖

“C言語何でも質問掲示板” へ戻る