みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

templateクラスについて

先ほど以下のようなプログラムを書いたのですがコンパイルを通すことができません。


//適当なポインタを保持するだけのクラス
template <class _type>
class hoge
{
private:
  //適当に変数を保持
  _type val;

public:
  //コンストラクタで適当に値をセット
  hoge() : val( 0 ){}

  //このクラスから唯一ポインタを引っ張ってくる方法
  friend _type getVal( const hoge& foo )
  {
    // そのまま返す
    return foo.val;
  }
};

void func( const hoge<int>& foo )
{
  //値を引き出す
  getVal( foo );
}

void main()
{
  //実体化
  hoge<int> foo;

  //値を引き出す
  getVal( foo );

  //関数の先で値を引き出す
  func( foo );
}

上記のようなプログラムを書いたのですが、main関数内でgetValを呼び出す場合はとくに問題ないのですがfunc関数を呼び出してfunc関数内でgetValを呼び出すと

error C3861: 'getVal': 識別子が見つかりませんでした
error C2365: 'getVal' : 再定義; 以前の定義は '以前は不明な識別子' でした。
コンパイルされたクラスの テンプレート のインスタンス化 'hoge<_type>' の参照を確認してください

というエラーが出てしまいます。
func関数の引数を( const hoge<int>& foo )からvoid func( hoge<int> foo )のように参照渡しから実体渡しに変更するとコンパイルが通り、実行もできるのですが、なぜこれでコンパイルが通るのか理由がいまいちよくわかりません。
またやはり、コンストラクタ、デストラクタの問題などから実体渡しより、参照渡しを使いたいのですがどのようにプログラムを書けば今回の問題を解決できますでしょうか。
よろしくおねがいします。

/*
VisualStudio2005 AcademicEdition
MicroSoft WindowsXP Professional 32bit
*/

投稿日時 - 2009-07-13 00:55:17

QNo.5120974

困ってます

質問者が選んだベストアンサー

 こんにちは。度々すみません。

 friendに別のテンプレートを付けておき、外側でhogeのスコープを外して別のテンプレートでfriendの中身を書いても解決出来ます。此方の方が良いかも。

 以下で出来ます。
//適当なポインタを保持するだけのクラス
template <class _type>
class hoge
{
private:
//適当に変数を保持
_type val;

public:
//コンストラクタで適当に値をセット
hoge() : val( 0 ){}

//このクラスから唯一ポインタを引っ張ってくる方法(別のテンプレートを与える)
template<class _type2>
friend _type2 getVal( const hoge<_type2>& foo );
};

//hogeのスコープを外して与えたテンプレートで中身を書く
template<class _type2>
_type2 getVal(const hoge<_type2>& foo)
{
// そのまま返す
return foo.val;
}

投稿日時 - 2009-07-13 11:05:25

このQ&Aは役に立ちましたか?

2人が「このQ&Aが役に立った」と投票しています

回答(3)

ANo.2

 こんにちは。

 VC++のfriendをテンプレートで使用すると、色々と問題があるから厄介です。
 func関数を以下の様にテンプレートにするか、

template<class _type>
void func( const hoge<_type>& foo )
{
//値を引き出す
getVal( foo );
}

 又はfriendを止めてstaticにして、hoge<int>::getVal( foo )にすれば罷り通るみたいです。

//適当なポインタを保持するだけのクラス
template <class _type>
class hoge
{
private:
//適当に変数を保持
_type val;

public:
//コンストラクタで適当に値をセット
hoge() : val( 0 ){}

//このクラスから唯一ポインタを引っ張ってくる方法
static _type getVal( const hoge<_type>& foo )
{
// そのまま返す
return foo.val;
}
};

void func( const hoge<int>& foo )
{
//値を引き出す
hoge<int>::getVal( foo );
}

void main()
{
//実体化
hoge<int> foo;

//値を引き出す
hoge<int>::getVal( foo );

//関数の先で値を引き出す
func( foo );
}

投稿日時 - 2009-07-13 10:52:20

ANo.1

コンパイラのバグみたいです。
VC 2008ではコンパイルが通ります。
理由は分からないですが、
funcの定義の前に以下の1行を書いておくとVC 2005でもコンパイルが通りました。

void dummy(hoge<int>){}

投稿日時 - 2009-07-13 04:42:08

あなたにオススメの質問