クラステンプレートのメンバ関数の動的参照について

解決


おバカさん  2013-02-11 10:10:45  No: 73622  IP: 192.*.*.*

今Visual C++でC++を勉強しています。
クラステンプレート内のメンバ関数動的参照で行き詰りました。
下記コードのエラーが取れません。

template <class Type> class Check
{
  int a;

  enum Opes{ ADD, SUB, MUL, OPES };

  Type fadd( Type b ) const{ return a + b; }
  Type fsub( Type b ) const{ return a - b; }
  Type fmul( Type b ) const{ return a * b; }

  Type ope( Opes op, Type b ) const
  {
    static Type (*opes[OPES])( Type ) = { this->fadd, this->fsub, this->fmul };
    return opes[op]( b );
  }

public:
  Check( int v ): a( v ){}

  Type operator+( int b ) const{ return ope( ADD, b ); }
  Type operator-( int b ) const{ return ope( SUB, b ); }
  Type operator*( int b ) const{ return ope( MUL, b ); }
};

int main( void )
{
  Check<int> a = 100;
  std::cout << "a + 500 = " << a + 500 << '\n';
  std::cout << "a - 500 = " << a - 500 << '\n';
  std::cout << "a * 500 = " << a * 500 << '\n';
  return 0;
}

多分、コンパイラーは、
ope関数内のopes関数ポインター配列の初期化子が特定できずエラーを出しているのでしょうが、
どのように具現化したメンバ関数を指定すれば良いのかお教えいただけないでしょうか?

編集 削除
おバカさん  2013-02-11 10:46:33  No: 73623  IP: 192.*.*.*

すみません。先ほど提示したソースコードに該当箇所以外に不具合がありました。
正しくは下記の通りです。引き続きご回答お願いいたします。

#include <iostream>

template <class Type> class Check
{
  int a;

  enum Opes{ ADD, SUB, MUL, OPES };

  Type fadd( const Type b ) const{ return a + b; }
  Type fsub( const Type b ) const{ return a - b; }
  Type fmul( const Type b ) const{ return a * b; }

  Type ope( Opes op, Type b ) const
  {
    static Type (*opes[OPES])( Type ) = { this->fadd, this->fsub, this->fmul };
    return opes[op]( b );
  }

public:
  Check( int v ): a( v ){}

  Type operator+( const Type b ) const{ return ope( ADD, b ); }
  Type operator-( const Type b ) const{ return ope( SUB, b ); }
  Type operator*( const Type b ) const{ return ope( MUL, b ); }
};

int main( void )
{
  Check<int> a = 100;
  std::cout << "a + 500 = " << a + 500 << '\n';
  std::cout << "a - 500 = " << a - 500 << '\n';
  std::cout << "a * 500 = " << a * 500 << '\n';
  return 0;
}

# 今のところ、
# fadd、fsub、fmulを名無し空間(ファイルスコープ)として実装し、
# 問題の箇所を避けています。(^^;)

編集 削除
επιστημη  URL  2013-02-11 13:39:42  No: 73624  IP: 192.*.*.*

これでいいのかしらん?

#include <iostream>

template <class Type> class Check {
  int a;
  
  enum Opes{ ADD, SUB, MUL, OPES };

  Type fadd( const Type b ) const{ return a + b; }
  Type fsub( const Type b ) const{ return a - b; }
  Type fmul( const Type b ) const{ return a * b; }

  Type ope( Opes op, Type b ) const {
    static Type (Check::*opes[OPES])( Type ) const = { &Check::fadd, &Check::fsub, &Check::fmul };
    return (this->*opes[op])( b );
  }

public:
  Check( int v ): a( v ){}

  Type operator+( const Type b ) const{ return ope( ADD, b ); }
  Type operator-( const Type b ) const{ return ope( SUB, b ); }
  Type operator*( const Type b ) const{ return ope( MUL, b ); }
};

int main( void ) {
  Check<int> a = 100;
  std::cout << "a + 500 = " << a + 500 << '\n';
  std::cout << "a - 500 = " << a - 500 << '\n';
  std::cout << "a * 500 = " << a * 500 << '\n';
  return 0;
}

編集 削除
おバカさん  2013-02-13 11:37:21  No: 73625  IP: 192.*.*.*

επιστημη様、ありがとうございます。
なるほど、C++はCやJavaに比べると複雑ですね。
C++脳になれるのであろうか・・・。

初期化子はご指摘と同じ事も試していたのですが、
関数のポインター名にクラス名を付与したものは試していませんでした。
と言うより、まったく頭によぎる事すらありませんでした。
単純に返却値と引数、関数の型が合致するだけではダメだったのですね。
その関数の名前空間までも・・・なるほど。

大変、スッキリし、勉強になりました。
ありがとうございました。

編集 削除