2009-07-10 3 views
14

Tôi có một lớpCó thể lấy loại giá trị từ một trình lặp vòng tùy ý (C++) không?

template <typename Iterator, typename Value> 
class Foo { 
public: 
    Foo(const Iterator& it) { ... } 
    ... 
private: 
    map<Value, int> m_; 
    } 
}; 

Có cách nào để thoát khỏi giá trị trong mẫu không? Iterator có thể hoặc không thể là một trình lặp STL, nhưng nó được đảm bảo rằng * nó là Giá trị.

Tôi biết về iterator_traits<T>::value_type cho trình lặp STL, nhưng tự hỏi liệu có cách nào để tự động nhận loại Giá trị cho loại Iterator tùy ý không?

Một trick Tôi đang suy nghĩ về - nói rằng, chúng tôi có một lớp helper

template <typename Iterator, typename Value> 
class Bar { 
public: 
    Bar(const Iterator& dummy_iterator, const Value& dummmy_value) {} 
    ... 
}; 

Sau đó, nếu chúng ta nhanh chóng Bar như Bar (nó, * nó), loại giá trị gia tăng sẽ được biết đến trong Bar. Nhưng tôi không thể tìm ra cách tốt để kết hợp Bar với Foo.

Trả lời

18

Bất kỳ thiết bị lặp nào sẽ cung cấp iterator_traits<Iterator>::value_type. Nếu không, thì nó không phải là một trình lặp. ISO C++ 2003 24.3.1 [lib.iterator.traits] "đặc điểm Iterator":

Để thực hiện các thuật toán chỉ về của vòng lặp, nó thường là cần thiết để xác định giá trị và sự khác biệt loại tương ứng với một loại vòng lặp cụ thể. Theo đó, nó là cần thiết rằng nếu Iterator là loại của một iterator, các loại

iterator_traits<Iterator>::difference_type 
iterator_traits<Iterator>::value_type 
iterator_traits<Iterator>::iterator_category 

được định nghĩa là kiểu của iterator sự khác biệt, kiểu giá trị và loại iterator, tương ứng.

Ngoài ra, không có cách chung để có được loại biểu thức C++ tùy ý. C++ 0x sẽ sửa chữa nó bằng cách cung cấp decltype.

+0

Cảm ơn, tham chiếu đến tiêu chuẩn ISO C++ rất hữu ích. –

1

Rất tiếc. Cách chính xác để loại bỏ Value là sử dụng iterator_traits như bạn đã đề xuất.

Nếu trình lặp không phải STL của bạn là con trỏ thông thường, thì bạn sẽ nhận được các typedef miễn phí chính xác cho iterator_traits. Nếu không, lớp không lặp STL phải xác định đúng typedef.

Xem iterator traits documentation để biết thêm thông tin.

1

Để nhận được loại giá trị của các câu trả lời trước của trình lặp là chính xác.

Nhưng còn nhiều hơn thế nữa. Bí quyết bạn đang nghĩ đến sẽ không hoạt động với lớp học. Nếu Bar là một chức năng như:

template <typename Iterator, typename Value> 
void bar(const Iterator& dummy_iterator, const Value& dummmy_value) {} 

sau đó loại trừ sẽ làm việc cho bar(it, *it) và bạn sẽ có kiểu giá trị bên trong của bar. (Nhưng hãy nhớ rằng để sử dụng thủ thuật này, bạn sẽ vẫn phải có một trình lặp không thể chối cãi, nó không phải lúc nào cũng tốt - cách xử lý chuỗi rỗng sau đó?)

Sử dụng lớp học Bar bạn sẽ phải cung cấp đối số mẫu IteratorValue theo cách thủ công vì không có khấu trừ loại cho lớp học và sử dụng Bar(it, *it) sẽ không biên dịch.

+0

Cảm ơn! Tôi đã tìm hiểu về việc sử dụng thanh như chức năng, nhưng nghĩ rằng có lẽ tôi đang thiếu một cái gì đó. –