2013-06-26 8 views
7

私が作った非常に複雑なオブジェクトの基本的な算術演算子をオーバーロードする必要があります。これまでのところ、私は首尾よくoperator*を実装しました。今度はoperator+などが必要です。operator*のコードは非常に大きいですが、operator*operator+の唯一の違いは、複素数に*の代わりに+を使用する1行になります。この行は、何度も呼び出されるループの内部にあるので、私はそれを効率的にしたいと思います。これは関数ポインタを暗示しているようです。 (私が間違っている場合は私を訂正してください)オペレータを関数のテンプレートパラメータとして渡す

これはテンプレートには最適です。しかし、私は正しい構文については迷っています。

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); 
} 

この質問は関連しています:"function passed as template argument"私は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]); // 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); 
} 
+1

'std :: complex'はクラステンプレートなので、' std :: complex 'が必要です。しかし、それでも 'complex :: operator *'と 'complex :: operator +'は*メンバ関数*です。操作するには 'complex 'のインスタンスがなくても、それらを渡すことはできません。 – Praetorian

+0

あなたが得たエラーを投稿してください。興味深い質問については –

+1

+1。私はまた、この質問を見つけました - [C++ポインターの演算子](http://stackoverflow.com/questions/4176895/c-pointers-to-operators)関連性と興味深い。 – keelar

答えて

4

私はstd::plus<std::complex>std::multiplies<std::complex>はあなたが「何だと思います私はあなたの質問を理解しているとは100%確信していません。あなたのコードスニペットは私たちに表示されていませんか?

+0

+1これはOPが探しているものだと思うが、それは 'plus >'と 'multiplies >' – Praetorian

+0

@Praetorianであるべきである: 'plus'と' multiplies'を使うことができる'std'スコープを指定せずに? – keelar

+0

+1はい、これは私が欲しいもののように見えますが、大丈夫です(@Praetorianは正しいですが)。しかし、私はこれらの機能をどのように使用するのかを決めることはできません。コンパイラは私の行 'ComplexBinaryOp(f [i]、B.f [i])'にオブジェクトを返します。それについての助け? – Mike

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の定義を変更することで、同様のメンバ関数ポインタと同じことを行うことができると信じて。

+0

これらは役に立つ可能性のようです。私は物事を試して、あなたに戻って取得します。ありがとう! – Mike

+0

私の元の構文は、 'std :: complex :: operator *'を 'std :: multiplies'などに置き換えてもうまく動作します。あなたも動作しますが、あまり単純ではありません。 – Mike

+1

@Mike:うん、うまくいく。しかし、実際にファンクタインスタンスを取得するには、 'ComplexBinaryOp()(foo、bar)'と言う必要があります。それは、私の最初の例のように、内側または外側で行うこともできます。 –

関連する問題