- PR -

テンプレート内this使用によるコンパイルエラーC2664

投稿者投稿内容
やっぷ
会議室デビュー日: 2007/05/07
投稿数: 17
投稿日時: 2007-10-17 08:12
すみません、自己レスです。
解決策として挙げた、派生クラスの型自身をテンプレートパラメータ引数
とするやり方と、this ポインタのstatic_cast<>によるダウンキャスト、調べたら
Curiously Recurring Template パターン(CRTP)っていうやつなのかも…。
まとめ&自己備忘録として下記リンクを追記させて下さい。

http://blogs.wankuma.com/melt/archive/2007/06/20/81374.aspx
http://ml.tietew.jp/cppll/cppll/article/3480
http://discuss.develop.com/archives/wa.exe?A2=ind0210b&L=atl&P=7746
あとは「テンプレートメタプログラミング wiki」で検索、その中で、
Curiously Recurring Template パターン を検索。
囚人
ぬし
会議室デビュー日: 2005/08/13
投稿数: 1019
投稿日時: 2007-10-17 09:46
派生クラスをテンプレートパラメータにするのは良いんですけど、循環参照がなんとなく気持ち悪いですね。

ミニマムコードだからそう思うのかもしれないですけど、テンプレートを使う意味があまりないような。以下みたいじゃだめなんですか?

コード:
class Me{
public:
	void SetYou(Me* y){ m_you = y; }
	
	void SetYouOfYours_ItsMe(Me* y){
		y->SetYou(this);
	}

private: 
	Me* m_you; 
};

class A : public Me{};
class B : public Me{};



_________________
囚人のジレンマな日々
一郎
ぬし
会議室デビュー日: 2002/10/11
投稿数: 1081
投稿日時: 2007-10-17 10:00
想定されてるのは、AがBを型引数に取って、BがAを型引数に取るというような1対1の関係しかないんですかね。
やっぷさんのソースではAがBを、BがCを、CがAを、って形は無理ですよね。

こんなコードはどうですか。
コード:
class Base{
private:
	Base* m_you;
public:
	virtual void SetYouImpl( Base* y ){ m_you = y; }
};

template < class You > class BaseTemplate : public Base
{
public:
	void SetYou( You* y ){ SetYouImpl(y); }
	void SetYouOfYours_ItsMe( You* y ){
		y->SetYouImpl( this );
	}
};

class A;
class B;
class A : public BaseTemplate<B>{};
class B : public BaseTemplate<A>{};


ライブラリの外にはBaseクラスを公開しないようにするといい感じかと思います。
Tdnr_Sym
ぬし
会議室デビュー日: 2005/09/13
投稿数: 464
お住まい・勤務地: 明石・神戸
投稿日時: 2007-10-17 12:38
こんにちは。

引用:

やっぷさんの書き込み (2007-10-17 08:12) より:
Curiously Recurring Template パターン(CRTP)っていうやつなのかも…。



Curiously recurring template patternですか。
パターン名があったんですね。
ATLやWTLを真っ先に思い浮かべました。
ATLのソースコードを覗いてみると、たいてい
コード:
template <class Derived>
・・・・

Derived* pT = static_cast<Derived*>(this);


という感じでキャストに使ってますね。
やっぷ
会議室デビュー日: 2007/05/07
投稿数: 17
投稿日時: 2007-10-17 17:08
囚人さん、ありがとうございます。

ミニマムコードと同じ結果が得られるという意味ではこれで十分だと
思います。まさにシンプルイズベストですね^^;
しかし、すでに説明させて頂いておりますように、私の本来の目的は、
「互いに参照し合い、かつ互いに連携して動作する、複数の異種基本クラスの
挙動を、複数のテンプレートからなる集まりとして記述したい」
ということですので、残念ながらこれでは私のケースには応用できません。
Me<A>, Me<B> とサンプルコードでは同じテンプレートMe<>を用いましたが、
これも行数削減のためで、本来は、
Twitter< class F, class W >, Flicker< class W >, Whisper< class W >
のように複数テンプレートがあり、しかもそれぞれがめいめいに、一つ以上の、
それぞれの派生クラスを想定した、テンプレートパラメータを受け取るような
複雑なケースなのです。
(もっとも、今回はCRTPを採用していくとすると、上記テンプレートパラメータ
 に己自身の型を受け取る引数を更に追加することになります…。)

一郎さん、ありがとうございます。

なかなかこれも一つの技術なのかも知れませんね^^;。使いような気もします。
ただ今私が見て思うのは、this が渡される可能性のあるあらゆる関数について、
Impl 関数を用意できるのだろうかということです。まして上記の私のケースの
ような複雑なテンプレートセットの場合ですね…。それぞれのメソッド数も少なくないですし…。
だからメンテナンスの問題っていうのとあとは関数呼び出し段が一つ増えるとか
でしょうか。

Tdnr_Symさん、CRTPのWikiの説明、わかり易いですね!

ATLとかWTLは私はよく知らないのですが、似たようなニーズがあり、同じようなことを
考えた人が、既にいたということだけでも、ちょっと勇気付けられています。
本件に関してまた新たな壁にぶち当たらないことを祈りつつ…。


[ メッセージ編集済み 編集者: やっぷ 編集日時 2007-10-17 17:27 ]

スキルアップ/キャリアアップ(JOB@IT)