C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[5]: template を使ったクラスについて


(過去ログ 56 を表示中)

[トピック内 6 記事 (1 - 6 表示)]  << 0 >>

■31436 / inTopicNo.1)  template を使ったクラスについて
  
□投稿者/ 雲 (24回)-(2009/01/22(Thu) 07:22:47)

分類:[C/C++] 

template<typename T>
class AAA{
public:
class BBB{
public:
int bbb;
}

BBB func(){ return( BBB() ); }

};

と書くと特に問題なく動作します。

ここで、BBB func(){ return( BBB() ); } を AAA の外に出して、

template<typename T>
class AAA{
public:
class BBB{
public:
int bbb;
}

BBB func();
};


template<typename T>
AAA<T>::BBB func() <-------------------ここがダメらしい
{
return( AAA::BBB() );
}

とすると、何故か、『依存名は型ではありません』と言ってコンパイラに
怒られてしまいます。

どうも、戻り値にAAA<T>::BBBと書くのがダメみたいなのですが、理由が良く
わかりません。

なにがいけないのでしょう?

引用返信 編集キー/
■31437 / inTopicNo.2)  Re[1]: template を使ったクラスについて
□投稿者/ 774RR (297回)-(2009/01/22(Thu) 08:47:45)
後者の BBB や func をどう実用的に使いうるのか微妙に疑問が残るところだけど
まあ単純に技術的解説に絞ってみよう

後者でダメと書かれているほうの func は「非メンバー関数」なのだが、そこは理解できているかい?
どれかのクラスに属しているわけではない関数 main とか printf とかと同じ扱いなわけだ。
struct foo {
  int func(); // これは foo::func
};
int func(); // これは非メンバ func
提示コード後者は、こういう状況になっているわけだ。この2つの func は無関係な独立した存在。

つーことで、やりたいことがメンバー関数 func の定義を、クラス定義外で行うことであるとするなら
書き方の方針はこういうことになる
1.メンバー関数 func は AAA のメンバーである → AAA::func と書かなきゃならない
2.AAA は実は template であるため AAA<T> と書かなきゃならない
3.func の返却値の型は BBB なんだが、これは AAA の型だから AAA<T>::BBB と書く必要がある
と、この順に考え+実装していくことになる

1.の時点で *** AAA::func() { ... } と書ける。
  この時点で返却値の型はまだ考えていないので *** と適当にごまかしておく
2.を適用して *** AAA<T>::func() { ... } と修正
3.を適用して AAA<T>::BBB AAA<T>::func() { ... } となる
4.全体を template 化して
template<typename T> AAA<T>::BBB AAA<T>::func() { ... } で完了。

引用返信 編集キー/
■31452 / inTopicNo.3)  Re[2]: template を使ったクラスについて
□投稿者/ アキラ (150回)-(2009/01/22(Thu) 11:17:28)
アキラ さんの Web サイト
No31437 (774RR さん) に返信

> 4.全体を template 化して
> template<typename T> AAA<T>::BBB AAA<T>::func() { ... } で完了。

BBBは依存名(dependent-name)なのでtypename付けないとダメですね。

template <typename T>
typename AAA<T>::BBB AAA<T>::func()
{
}


参考までに今日私が投稿したバグ報告

「C++で、依存名に対してtypenameを付けなくてもコンパイルが通ってしまう」
https://connect.microsoft.com/VisualStudioJapan/feedback/ViewFeedback.aspx?FeedbackID=403295

引用返信 編集キー/
■31461 / inTopicNo.4)  Re[3]: template を使ったクラスについて
□投稿者/ 774RR (299回)-(2009/01/22(Thu) 12:07:21)
あうっ、御意。
で、俺もアキラ氏もわざと書いていない関数本体部分において AAA<T>::BBB を使うなら
やはりそこでも typename が必要だったりするわけで (template の中では)
最初の提示サンプルと同等のことがしたい(=一時オブジェクトを生成して返したい)のであれば
template<typename T>
typename AAA<T>::BBB AAA<T>::func() { typename AAA<T>::BBB(); }

というわけで俺の No31437 に追加しておこう
3.func の返却値の型は BBB なんだが、これは AAA の型だから AAA<T>::BBB と書く必要がある

AAA の <T> を確定した上ではじめて決まる (AAA 所属の) 型だから AAA<T>::BBB と書く必要がある
この記述を template の内側にて行う場合には依存名なのでさらに typename 記述が必要
template の外側では要らない (つけちゃダメ) 。

// 特殊化はもはや template ではない
template<>
AAA<int>::BBB AAA<int>::func() { return AAA<int>::BBB(); } // typename つけちゃダメ

引用返信 編集キー/
■31491 / inTopicNo.5)  Re[4]: template を使ったクラスについて
□投稿者/ 雲 (25回)-(2009/01/22(Thu) 20:42:27)
みなさん。ご回答ありがとうございます。

私も調べてみたところ、以下のようなページを見つけました。

【テンプレートあれこれ (4) -- typename の役割】
http://www.fides.dti.ne.jp/~oka-t/cpplab-template-4.html

最初に質問を書いたときに、少し、間違ってしまって混乱させてしまいごめんなさい。

あと、もう一つ、不思議に思ったことを書いておきます。

template <typename T>
typename AAA<T>::BBB AAA<T>::func()
{
AAA<T>::BBB aaa; // <------- ここには、typename が必要ない?
}

上記は、VC2005ではコンパイルエラーにならないのですね。

なかなか、C++ は難しいです (^^)。





解決済み
引用返信 編集キー/
■31495 / inTopicNo.6)  Re[5]: template を使ったクラスについて
□投稿者/ アキラ (151回)-(2009/01/22(Thu) 21:21:58)
アキラ さんの Web サイト
No31491 (雲 さん) に返信
> あと、もう一つ、不思議に思ったことを書いておきます。
> 
> template <typename T>
> typename AAA<T>::BBB AAA<T>::func()
> {
> AAA<T>::BBB aaa; // <------- ここには、typename が必要ない?
> }
> 
> 上記は、VC2005ではコンパイルエラーにならないのですね。
 
それがコンパイルエラーにならないので、No31437で書いたように
Microsoftにバグ報告出してます。
typenameは必要です。 

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -