2012-03-31 35 views
8

Sau khi cố gắng truy cập vào một lớp lưu trữ dễ dàng hơn một chút, tôi đã kết thúc trong một tình huống mà tôi không có nhiều kiến ​​thức. Và, việc tìm kiếm những người đang cố gắng làm điều tương tự như tôi không dễ dàng.C++ Array Subscript Operator Template

Điều tôi đang cố gắng làm là có một lớp lưu trữ một mảng giá trị dưới dạng chuỗi nội bộ, nhưng cho phép nhập kiểu đơn giản từ đầu của người dùng. Những gì tôi đã lên kế hoạch làm là sử dụng toán tử chỉ số mảng để trả về kiểu nào chúng chỉ định thông qua một khuôn mẫu. Mặc dù, nó âm thanh tốt hơn rất nhiều so với nó hoạt động trong thực tế. Dưới đây là một ví dụ đơn giản về những gì tôi đang làm, để cung cấp cho bạn ý tưởng về cách hoạt động của nó nên.

class StringList 
{ 
    public: 
    template <typename T> 
    T operator[](const int i) 
} 

Từ đó, tôi sẽ xác định một vài mẫu cụ thể và bất kỳ người dùng nào cũng có thể dễ dàng xác định thêm nếu cần. Nhưng, vấn đề lớn nhất với điều này là, tôi không biết làm thế nào để gọi toán tử subscript với một mẫu. Lúc đầu, tôi giả định sau đây (mà dường như là không chính xác), xem xét nó tương tự như cách tiêu chuẩn gọi một phương pháp mẫu.

StringList list; 
T var = list<T>[0]; 

Có ai biết cách thích gọi các nhà điều hành subscript làm mẫu không? Hoặc, tôi nên tránh làm điều này, và sử dụng một phương pháp được đặt tên?

+0

Tôi sẽ cảnh báo chống lại quá tải 'toán tử []' cho mục đích này khi toán tử quá tải được sử dụng tốt nhất khi chúng có ý nghĩa cú pháp. Bạn thường không viết những thứ như 'danh sách [0]', và tôi nghĩ rằng chi phí trí tuệ bổ sung không đáng giá. Tại sao không chỉ tạo một phương thức 'get' và gọi' list.get (0) '? – templatetypedef

+0

@templatetypedef Tôi đồng ý hoàn toàn. Tôi đã nhiều hơn khả năng sẽ chỉ dính vào một chức năng được đặt tên như có được, xem xét tôi thậm chí không hiểu làm thế nào bạn sẽ viết một mẫu như thế này. Nhưng, tôi tò mò muốn biết nó sẽ được viết như thế nào, bất kể tôi có cần sử dụng nó hay không. – TheCodeBroski

Trả lời

10

Cách duy nhất để gọi nhà điều hành của bạn là viết rõ ràng list.operator[]<T>().

Có hai cách cơ bản ra:

  1. Viết một hàm template như list.get<int>() (theo đề nghị của templatetypedef)
  2. Return một proxy với cuộc nói chuyện tự động để T.

Mã này sẽ như thế nào:

// in the class 
struct proxy { 
    proxy(StringList *list, int i) : list(list), i(i) {} 
    StringList *list; 
    int i; 
    template <typename T> 
    operator T() { return list->get<T>(i); } 
}; 

proxy operator[](int i) { return proxy(this, i); } 

template <typename T> 
T get(int i) { return ...; T(); } 

// how to use it: 
StringList list; 
int var = list.get<int>(0); 
float var2 = list[0]; 
+1

Tôi phải thừa nhận rằng tôi không hoàn toàn hiểu được giải pháp dựa trên proxy của bạn. Bạn có phiền xây dựng một chút không? Mục đích của 'T get (int i) {return ...; T(); } '? Làm thế nào là 'proxy operator [] (int i) {return proxy (điều này, i); } 'liên quan đến' StringList'? Dòng 'float var2 = list [0];' hoạt động như thế nào? Kiến thức của tôi khá ít về kỹ thuật C++ nâng cao có thể là lý do tại sao mặc dù. :-) –

4

Tôi nghĩ rằng không có cú pháp để vượt qua các thông số mẫu để các cuộc gọi tự nhiên của operator []. Có thể bạn sẽ cần phải gọi:

T var = list.operator[]<T>(0); 

Giống như bạn làm với các chức năng mẫu bình thường, vì vậy không có vấn đề gì khi sử dụng quá tải của nhà điều hành tại đây.