2013-03-22 29 views
7

Trong C++ 98, tôi thường sử dụng sau đây để khai báo một biến trong kiểu giá trị của một iterator:Làm thế nào để khai báo giá trị của một iterator qua decltype

typename std::iterator_traits<Iterator>::value_type value; 

Trong C++ chúng ta có 11 decltype và tôi đã nghĩ cách dễ nhất để suy ra kiểu giá trị là:

decltype(*iterator) value; 

Thật không may cho hầu hết các vòng lặp, các loại * iterator là value_type & và không VALUE_TYPE. Bất kỳ ý tưởng, mà không có các lớp sửa đổi loại, làm thế nào để xoa bóp ở trên vào năng suất value_type (và không phải bất kỳ tài liệu tham khảo)?


Tôi không nghĩ rằng câu hỏi này là không hợp lý vì sau đây là khá mạnh nhưng cuối cùng lại tạo ra một biến khác.

auto x = *iterator; 
decltype(x) value; 

Cũng lưu ý rằng tôi thực sự muốn suy luận kiểu và không chỉ là một ví dụ ví dụ nếu tôi muốn khai báo một std :: vector của các giá trị này.

+0

Loại biểu thức '* iterator' là' std :: iterator_traits :: reference', không phải 'value_type'. Điều này không nhất thiết là 'value_type &' và 'decltype' có thể báo cáo loại biểu thức khác với thực tế là tùy thuộc vào danh mục giá trị của nó. –

+0

Nếu bạn * chỉ * muốn kết hợp hai dòng chỉnh sửa của bạn, tương đương sẽ là 'typename std :: decay :: type value;', nhưng hãy kiểm tra câu trả lời bên dưới và chỉ don ' t làm điều đó :) Tôi chỉ cần thêm này như ['std :: decay'] (http://en.cppreference.com/w/cpp/types/decay) đã không được đề cập trong Q/A này trước đây. –

Trả lời

15

Tiếp tục sử dụng iterator_traits. decltype(*iterator) thậm chí có thể là một số loại lớp proxy lạ để làm những việc đặc biệt trong biểu thức *iter = something.

Ví dụ:

#include <iostream> 
#include <iterator> 
#include <typeinfo> 
#include <vector> 

template <typename T> 
void print_type() 
{ 
    std::cout << typeid(T).name() << std::endl; 
} 

template <typename Iterator> 
void test(Iterator iter) 
{ 
    typedef typename 
     std::iterator_traits<Iterator>::value_type iter_traits_value; 

    auto x = *iter; 
    typedef decltype(x) custom_value; 

    print_type<iter_traits_value>(); 
    print_type<custom_value>(); 
} 

int main() 
{ 
    std::vector<int> a; 
    std::vector<bool> b; 

    test(a.begin()); 
    test(b.begin()); 
} 

Output trên MSVC 2012:

int
int
bool
class std::_Vb_reference<struct std::_Wrap_alloc<class std::allocator<unsigned int>>>

Chúng không giống nhau.

+0

Nhưng như tôi đã đề cập trong bản chỉnh sửa của mình, các công trình sau đây: auto x = * iterator; giá trị decltype (x); –

+3

@GlenLow: Bạn chưa xác định "công trình". Xem chỉnh sửa của tôi để trả lời (aschepler, chỉnh sửa như bạn vui lòng). – GManNickG

+1

+1 cho chỉnh sửa của @ GManNickG. ; -] – ildjarn

1

Đối với trường hợp sử dụng này, tôi thích std :: phân rã. Tôi muốn sử dụng

std::vector<int> vec; 
using value_type = typename std::decay< decltype(*begin(vec)) >::type; 
static_assert(std::is_same< int, value_type >::value, "expected int"); 
+0

Cảm ơn gợi ý, nó hoạt động (và tôi đã học được điều gì đó mới!) Nhưng nó không kém phần chi tiết hơn 'std :: iterator_traits :: value_type' khi tôi đã có loại Iterator. –

+0

đúng. iterator_traits <> là con đường để đi. Tôi thực sự đang sử dụng đề xuất của mình nhiều hơn khi tôi có, ví dụ: loại vùng chứa không xác định. nếu bạn có loại trình vòng lặp, bạn chắc chắn đúng. –

+0

Tôi nên lưu ý rằng biểu thức này có thể không hoạt động ở nơi mà kiểu tham chiếu của trình lặp là một số proxy nghịch đảo, như trong 'std :: vector ' chuyên môn được ghi chú ở trên. –

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