8

作成したいくつかの非常に複雑なオブジェクトの基本的な算術演算子をオーバーロードする必要があります。これまでのところ、実装に成功しましたoperator*。今はoperator+などが必要です。 のコードoperator*は非常に大きいですが、 と の唯一の違いはoperator*、いくつかの複素数の代わりoperator+に使用する 1 行です。この行は、何度も呼び出されるループ内にあるため、関数ポインターがないように見える効率的なものにしたいと考えています。(間違っていたら訂正してください。)+*

これはテンプレートの完璧な使い方のようです。しかし、正しい構文については途方に暮れています。ComplicatedObjectクラス定義内で次のようなことを考えています:

template <typename ComplexBinaryOp>
ComplicatedObject BinaryOp(const ComplicatedObject& B) const {
  // Do lots of stuff
  for(unsigned int i=0; i<OneBazillion; ++i) {
    // Here, the f[i] are std::complex<double>'s:
    C.f[i] = ComplexBinaryOp(f[i], B.f[i]);
  }
  // Do some more stuff
  return C;
}

inline ComplicatedObject operator*(const ComplicatedObject& B) const {
  return BinaryOp<std::complex::operator*>(B);
}

inline ComplicatedObject operator+(const ComplicatedObject& B) const {
  return BinaryOp<std::complex::operator+>(B);
}

この質問は関連しています:「テンプレート引数として渡された関数」。ただし、テンプレート引数として渡される関数は演算子ではありません。

私は考えられるあらゆる方法で構文をいじりましたが、コンパイラは常に構文が悪いと文句を言います。どうすればいいですか?

編集:

明確にするために、上記のコードに関して完全なソリューションと、人々が必要とする可能性のある追加の一般化を含めます。

template <typename ComplexBinaryOp>
ComplicatedObject BinaryOp(const ComplicatedObject& B) const {
  // Do lots of stuff
  for(unsigned int i=0; i<OneBazillion; ++i) {
    // Here, the f[i] are std::complex<double>'s:
    C.f[i] = ComplexBinaryOp()(f[i], B.f[i]); // Note extra ()'s
  }
  // Do some more stuff
  return C;
}

inline ComplicatedObject operator+(const ComplicatedObject& B) const {
  return BinaryOp<std::plus<std::complex<double> > >(B);
}

inline ComplicatedObject operator-(const ComplicatedObject& B) const {
  return BinaryOp<std::minus<std::complex<double> > >(B);
}

inline ComplicatedObject operator*(const ComplicatedObject& B) const {
  return BinaryOp<std::multiplies<std::complex<double> > >(B);
}

inline ComplicatedObject operator/(const ComplicatedObject& B) const {
  return BinaryOp<std::divides<std::complex<double> > >(B);
}
4

2 に答える 2

4

私はあなたが探しているものだと思いますstd::plus<std::complex>std::multiplies<std::complex>、あなたの質問を100%理解しているとは限りません(あなたのコードスニペットは、あなたが私たちに見せていないクラス内にありますか?)

于 2013-06-26T04:00:18.297 に答える
1

2 つのオプションがあります。実行時に関数を渡します。

#include <functional>

template <typename ComplexBinaryOp>
ComplicatedObject BinaryOp(const ComplicatedObject& B, ComplexBinaryOp op) const {
  // ...
    C.f[i] = op(f[i], B.f[i]);
  // ...
}

// functor wrapping member function pointer
BinaryOp(B, std::mem_fn(&std::complex<double>::operator+));

// standard-issue functor
BinaryOp(B, std::plus<std::complex<double>>());

または、コンパイル時に渡します。

// or another floating-point type
typedef double (*ComplexBinaryOp)(double, double);

template <ComplexBinaryOp op>
ComplicatedObject BinaryOp(const ComplicatedObject& B) const {
  // ...
    C.f[i] = op(f[i], B.f[i]);
  // ...
}

// non-member function
template<class T>
std::complex<T> add_complex(const std::complex<T>& a, const std::complex<T>& b) {
  return a + b;
}

// non-member function pointer
BinaryOp<add_complex<double>>(B);

の定義を変更することで、メンバー関数ポインターでも同じことができると思いますComplexBinaryOp

于 2013-06-26T04:04:36.870 に答える