2013-06-26 49 views
7

Tôi phải quá tải toán tử số học cơ bản đối với một số đối tượng rất phức tạp mà tôi đã thực hiện. Cho đến nay, tôi đã triển khai thành công operator*; bây giờ tôi cần operator+, vv Mã cho operator* là rất lớn, nhưng sự khác biệt duy nhất giữa operator*operator+ sẽ là một dòng mà tôi sử dụng + thay vì * trên một số số phức. Dòng này sẽ nằm bên trong một vòng lặp được gọi nhiều lần, vì vậy tôi muốn nó có hiệu quả, điều này dường như ngụ ý không có con trỏ hàm nào. (Sửa tôi nếu tôi sai.)Vượt qua toán tử như tham số mẫu chức năng

Điều này có vẻ như là một cách sử dụng hoàn hảo cho các mẫu. Nhưng tôi thua lỗ đúng cú pháp. Tôi đang nghĩ đến một cái gì đó như thế này bên trong định nghĩa lớp 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); 
} 

Câu hỏi này có liên quan: "function passed as template argument". Nhưng các hàm được truyền như các đối số mẫu không phải là toán tử.

Tôi đã sử dụng cú pháp theo mọi cách tôi có thể nghĩ, nhưng trình biên dịch luôn phàn nàn về cú pháp không hợp lệ. Làm thế nào tôi nên làm điều này?

Edit:

Để rõ ràng, tôi bao gồm các giải pháp hoàn chỉnh về mã của tôi ở trên, cùng với sự khái quát thêm người có thể cần:

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' là một mẫu lớp, vì vậy bạn cần' std :: complex '. Nhưng ngay cả sau đó, 'phức tạp :: toán tử *' và 'phức tạp :: toán tử +' là * hàm thành viên *. Bạn không thể vượt qua chúng xung quanh mà không có một thể hiện của 'phức tạp ' để hoạt động trên. – Praetorian

+0

Lỗi bài đăng bạn đang nhận được. –

+1

+1 cho câu hỏi thú vị. Tôi cũng tìm thấy câu hỏi này - [C++ con trỏ tới toán tử] (http://stackoverflow.com/questions/4176895/c-pointers-to-operators) có liên quan và thú vị. – keelar

Trả lời

4

Tôi nghĩ std::plus<std::complex>std::multiplies<std::complex> là những gì bạn' đang tìm kiếm, nhưng tôi không chắc chắn 100% là tôi hiểu câu hỏi của bạn (là đoạn mã của bạn trong một lớp bạn không cho chúng tôi thấy?)

+0

+1, tôi nghĩ rằng đây là những gì OP đang tìm kiếm quá, nhưng nó phải là 'cộng >' và 'nhân >' – Praetorian

+0

@Praetorian: vì vậy 'plus' và' multiplies' có thể được sử dụng mà không chỉ định phạm vi 'std'? – keelar

+0

+1 Có, điều này có vẻ như những gì tôi muốn, được rồi (mặc dù @Praetorian là đúng). Nhưng tôi không thể tìm ra cách sử dụng các chức năng này. Các đối tượng trình biên dịch đối với dòng của tôi 'ComplexBinaryOp (f [i], B.f [i])'. Bất kỳ trợ giúp về điều đó? – Mike

1

Bạn có hai tùy chọn. Vượt qua chức năng trong thời gian chạy:

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

Hoặc vượt qua nó tại thời gian biên dịch:

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

Tôi tin rằng bạn có thể làm tương tự với con trỏ hàm thành viên cũng bằng cách thay đổi định nghĩa của ComplexBinaryOp.

+0

Những giao diện này giống như các khả năng hữu ích. Tôi sẽ thử mọi thứ và lấy lại cho bạn. Cảm ơn! – Mike

+0

Biến cú pháp ban đầu của tôi hoạt động tốt, sau khi thay thế 'std :: complex :: operator *' bằng 'std :: multiplies', v.v. Bạn cũng làm việc, nhưng chúng tấn công tôi đơn giản hơn. – Mike

+1

@Mike: Yeah, cũng vậy. Tuy nhiên, bạn phải nói 'ComplexBinaryOp() (foo, bar)' để thực sự có được cá thể functor. Điều đó cũng có thể được thực hiện bên trong hoặc bên ngoài như trong ví dụ đầu tiên của tôi. –

Các vấn đề liên quan