2013-06-26 30 views
7

Yaptığım bazı çok karmaşık nesneler için temel aritmetik işlemcileri aşırı yüklemem gerekiyor. Şimdiye kadar, başarılı bir şekilde operator*; Şimdi operator+, vb gerekir. operator* için kod çok büyük, ancak operator* ve operator+ arasındaki tek fark, bazı karmaşık sayılar üzerinde * yerine * kullanıyorum bir satır olacaktır. Bu çizgi birçok kez çağrılan bir döngünün içinde olacaktır, bu yüzden etkin olmasını istiyorum, ki bu hiçbir işlev göstericisini ima eder. (Yanılıyorsam düzeltin.)Operatörü, işlev şablon parametresi olarak değiştir

Bu şablonlar için mükemmel bir kullanım gibi gözüküyor. Ama doğru sözdizimi konusunda bir kayıp yaşıyorum. Ben ComplicatedObject sınıf tanımı içinde böyle bir şey düşünüyorum:

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

Bu soru ilgilidir: "function passed as template argument". Ancak şablon argümanları olarak iletilen işlevler operatör değildir.

Düşünebildiğim her şekilde sözdizimi ile uğraştım, ancak derleyici her zaman hatalı sözdizimden şikayetçidir. Bunu nasıl yapmalıyım?

Düzenleme:

Anlaşılır olması için, insanların ihtiyaç duyabileceği genellemeler ile birlikte yukarıda kodumu açısından tam bir çözüm içerir:

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' bir sınıf şablonu, yani std :: complex '. Ancak o zaman bile, ' :: operator * 've karmaşık :: operator +' karmaşık * üye işlevleri * vardır. Çalıştırmak için ' 'karmaşık bir örneği olmadan bunları yalnızca geçiremezsiniz. – Praetorian

+0

Aldığınız hata mesajları. İlginç soru için –

+1

+1. Ayrıca bu soruyu - [C++ operatörler için işaretçiler] (http://stackoverflow.com/questions/4176895/c-pointers-to-operators) ilgili ve ilginç buldum. – keelar

cevap

4
ben std::plus<std::complex> düşünüyorum

ve std::multiplies<std::complex> 'what are you bakıyorum, ama% 100 emin değilim sorunuzu anlıyorum (bize göstermediğiniz bir sınıf içindeki kod parçacığınız mı?)

+0

+1, Bence OP'in de aradığı şey budur, ama 'artı > 've' çarpanı > ' – Praetorian

+0

@Praetorian olmalıdır: bu yüzden' plus' ve 'multiplies' kullanılabilir 'std' kapsamını belirtmeden? – keelar

+0

+1 Evet, bu istediğim şeye benziyor (Tamam, @Praetorian haklı olsa da). Ama bu işlevleri nasıl kullanacağımı tam olarak anlayamıyorum. Derleyici, 'ComplexBinaryOp (f [i], B.f [i]) 'satırına gider. Bunun hakkında herhangi bir yardım? – Mike

1

İki seçeneğiniz var.

#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>>()); 

Veya derleme sırasında geçmek: zamanında işlevi geçmek

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

Sana ComplexBinaryOp tanımını değiştirerek de üye işlev işaretçileri ile aynı şeyi inanıyoruz.

+0

Bunlar kullanışlı olasılıklara benziyor. Bir şeyler deneyip sana döneceğim. Teşekkürler! – Mike

+0

Özgün sözdizimi işlerimi, std :: complex :: operator * 'yi std :: multiplies' vb. Ile değiştirdikten sonra, sadece iyi çalışıyor. – Mike

+1

@Mike: Evet, bu da işe yarıyor. Yine de, functor örneğini almak için, “ComplexBinaryOp() (foo, bar)” demek zorundasınız. Bu benim ilk örneğimde olduğu gibi içeride veya dışarıda da yapılabilir. –

İlgili konular