2009-07-12 35 views
31

Trong C++, bạn có thể có toán tử được sắp xếp trên lớp không? Cũng giống như vậy:Mẫu chức năng với toán tử

class MyClass { 
public: 
    template<class T> 
    T operator()() { /* return some T */ }; 
} 

Điều này thực sự dường như biên dịch tốt, nhưng sự nhầm lẫn do thỏa thuận như thế nào người ta sẽ sử dụng nó:

MyClass c; 
int i = c<int>(); // This doesn't work 
int i = (int)c(); // Neither does this* 

Thực tế là nó biên dịch ở tất cả các gợi ý với tôi rằng đó là doable, Tôi chỉ thua lỗ về cách sử dụng nó! Bất kỳ đề xuất, hoặc là phương pháp này sử dụng một không khởi động?

+1

Điều này có nghĩa là "điều này không hoạt động/không thực hiện điều này"? Chuyện gì xảy ra? –

+0

Trình biên dịch barfs về bạn, đó là những gì sẽ xảy ra :) – Toji

+0

Tôi thề tôi đã nhìn thấy câu hỏi này trên SO trước ... Tôi không thể tìm thấy nó mặc dù, vì vậy rõ ràng là không thể đổ lỗi cho bạn. – GManNickG

Trả lời

41

Bạn cần chỉ định T.

int i = c.operator()<int>(); 

Thật không may, bạn không thể sử dụng cú pháp cuộc gọi hàm trực tiếp trong trường hợp này.

Chỉnh sửa: Ồ, và bạn đang thiếu public: ở đầu định nghĩa lớp.

+1

Rất đẹp.Kudo trên câu trả lời nhanh chóng và chính xác! Thật không may đó là có lẽ để tiết cho sử dụng của tôi (kể từ khi mã của tôi được dự định sẽ được gọi bởi những người khác tôi muốn tránh nhầm lẫn) vì vậy tôi sẽ chỉ phải tìm một con đường khác. Cảm ơn một lần nữa! – Toji

+5

Có, có lẽ bạn nên định nghĩa phương thức 'get' thay vì' operator() '. Sau đó, bạn có thể viết 'c.get ()'. – avakar

+0

Trên thực tế, có một thành ngữ bay xung quanh được nhiều người sử dụng: chức năng nhận tự do (các bộ dữ liệu sử dụng 'get (some_tuple)', boost.variant sử dụng 'get (some_variant)'). Vì vậy, bạn sẽ trông giống như 'có được (c)', với 'get' được định nghĩa trong' MyClass''es không gian tên). –

18

Về cơ bản bạn có quyền. Nó là hợp pháp để xác định các toán tử khuôn mẫu, nhưng chúng không thể được gọi trực tiếp với các đối số mẫu rõ ràng.

Nếu bạn có điều hành này:

template <typename T> 
T operator()(); 

như trong ví dụ của bạn, nó chỉ có thể được gọi là như thế này:

int i = c.operator()<int>(); 

Tất nhiên, nếu đối số mẫu có thể được rút ra từ các đối số , bạn vẫn có thể gọi nó theo cách thông thường:

template <typename T> 
T operator()(T value); 

c(42); // would call operator()<int> 

Một giải pháp thay thế có thể làm cho gument một tài liệu tham khảo, và lưu trữ các kết quả đó, thay vì trả lại nó:

template <typename T> 
void operator()(T& value); 

Vì vậy, thay vì điều này:

int r = c.operator()<int>(); 

bạn có thể làm

int r; 
c(r); 

Hoặc có lẽ bạn chỉ cần xác định một hàm get<T>() đơn giản thay vì sử dụng toán tử.

4

Không phải bạn nghĩ đến việc

class Foo { 
    public: 
    template<typename T> 
    operator T() const { return T(42); } 
}; 

Foo foo; 

int i = (int) foo; // less evil: static_cast<int>(foo); 

live example. Điều này chứng tỏ bạn không cần phải xác định đối số mẫu, mặc dù xác nhận quyền sở hữu trong câu trả lời được chấp nhận.

+0

Làm việc trong trường hợp này, nhưng tôi đã nghĩ đến 'c ++'. Tôi có nghĩa là điều này không nên làm việc, và tôi là một hành vi lạm dụng các ký hiệu ở đó ... – kim366

+0

@ kim366: Vì điều đó không có ý nghĩa, nó khá là vô nghĩa khi nghĩ về nó. Nó không hoạt động, và nó không hoạt động. – MSalters

+0

Vâng, tôi biết điều đó .. Trông thật tuyệt, mặc dù: P – kim366

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