ページ 11

テンプレート化できません

Posted: 2007年5月13日(日) 18:54
by 組木紙織
簡単な行列計算のプログラムを作ったのですが、テンプレートをしようとしたらどうしても
コンパイルできなくて困ったのでこちらに書き込みをします。

ソースは添付してあるzipにテンプレートしていないもの<nontemplate.cpp>と(こちらは問題ないです)
自分で出来るとこまでテンプレート化してあるもの<template.cpp>を入れてあります。

適当に作ったので色々とコメントがあると思いますので、そちらもお願いします。

Re:テンプレート化できません

Posted: 2007年5月13日(日) 20:08
by Justy
 このあたりは最初にテンプレートをやろうとしたときに誰もが引っかかるところです。
 慣れてきた今でも付け忘れてしまうことがあるくらいに。


 結論からいいますとエラーとなっているところに [color=#d0d0ff" face="monospace]typename[/color]をつけると解決します。

typename は何故必要か
http://ray.sakura.ne.jp/template/typename.html

C++ Labyrinth
http://www.fides.dti.ne.jp/~oka-t/cppla ... ate-4.html


 一応修正したソースもつけておきました。diffで修正箇所を確認してみて下さい。

Re:テンプレート化できません

Posted: 2007年5月13日(日) 20:28
by Justy
 あ、ちなみに添付したソースでのリンクエラーの方はそのままにしてあります。

Re:テンプレート化できません

Posted: 2007年5月13日(日) 21:53
by 組木紙織
typename の使い方ありがとうございます。
なんとなくでしかわかっていないところが分かりました。

> あ、ちなみに添付したソースでのリンクエラーの方はそのままにしてあります。

一番やって欲しいものはリンクエラーを直すことだったので、リンクエラーもお願いできませんでしょうか?

Re:テンプレート化できません

Posted: 2007年5月13日(日) 22:30
by Justy
[color=#d0d0ff" face="monospace]friend std::ostream &operator<< (std::ostream &stream, Matrix<T> ob)[/color]
 ご存じだと思いますが、friendをつけた上でこのように書いた場合、
friendとなる対象はメンバ関数ではなく普通の関数になります。

 だからこそ実装側で
[color=#d0d0ff" face="monospace]template<typename T>
std::ostream &operator<<(std::ostream &stream, Matrix<T> ob)
{
    ....
}[/color]
 のように関数として書いたのだと思いますが、肝心の friend指定の方と定義が一致しません。
 なので、
[color=#d0d0ff" face="monospace]template<typename T>
class Matrix
{
    ....
    template <typenameT>
    friend std::ostream &operator<<(std::ostream &stream, Matrix<T> ob);	
    ....
};
[/color]
 とすれば一致してリンクエラーは消えるはずです。

Re:テンプレート化できません

Posted: 2007年5月13日(日) 23:44
by YuO
非常にややこしいところなのですが……。

クラステンプレートが,同一のテンプレート引数利用する関数テンプレートをfriendにしたい場合,
template <typename T> class C;
template <typename T> void func (const C<T>&);

template <typename T> class C
{
    /* ... */
    friend void func <T> (const c<t>&);
    /* ... */
};
のように書きます。

細かいことは,Justyさんがあげられていた,http://www.fides.dti.ne.jp/~oka-t/cpp-labyrinth.htmlを参照してください。

今回の場合,
template <typename T> class Matrix;
template <typename T> std::ostream & operator << (std::ostream & stream, Matrix<T> obj);

template <typename T> class Matrix
{
/* ... */
    friend std::ostream & operator << <T> (std::ostream & stream, Matrix<T> obj);
/* ... */
};
とやることになります。
# イディオムとして覚えておくのが一番かと。
個人的に考える一番の正解は,クラステンプレートのfriendはインラインで書け,ですが……。

Re:テンプレート化できません

Posted: 2007年5月14日(月) 21:32
by 組木紙織
出来ました。

コメントをくれたJustyさんYuOさんありがとうございます。

c++のテンプレート機能は私がまだなれていないだけかもしれませんが、
強力な割りに結構使いにくい感じがします。
もっと使いやすく改良をしてくれれば、c++を使う人が増えると思うのに。。

私はその強力で使いにくいことがc++を好きな理由なのですが。