2012-03-08 12 views
11

Giống như câu hỏi nói, tôi tự hỏi lý do cho điều đó. Vì tôi gặp lỗi khi cố gắng lấy khoảng cách giữa các thiết bị lặp không const và không phải là const.Tại sao std :: khoảng cách không hoạt động trên sự kết hợp của các biến lặp const và nonconst?

vector<int> v; 
auto it=v.begin(); 
auto cit=v.cbegin(); 
distance(it,cit); 


no matching function for call to ‘distance(__gnu_cxx::__normal_iterator<int*, std::vector<int> >&, __gnu_cxx::__normal_iterator<const int*, std::vector<int> >&) 

Từ hiểu biết hạn chế về trình vòng lặp của tôi, tôi không thấy lý do tại sao nó không hoạt động.

Trả lời

19

Bạn có trình lặp lặp có thể thay đổi và một trình lặp không đổi trong cuộc gọi đến std::distance, vì vậy việc khấu trừ đối số mẫu không thành công. Bạn có thể sửa lỗi này bằng cách chỉ định đối số mẫu một cách rõ ràng.

std::vector<int> v; 
auto i1 = v.begin(); 
auto i2 = v.cbegin(); 

auto dist = std::distance<std::vector<int>::const_iterator>(i1, i2); 
6

Đó là bởi vì std::distance() chỉ mất một mẫu tham số:

template <class InputIterator> 
iterator_traits<InputIterator>::difference_type 
distance(InputIterator first, InputIterator last); 

Do đó, firstlast phải chuyển đổi thành cùng loại, và độ phân giải mẫu sẽ tiếc là không xem xét rằng vector<int>::iterator là mui trần để vector<int>::const_iterator.

+0

hmm tại sao chúng không tạo mẫu với 2 tham số mẫu? Có thể làm điều đó trong cpp core lang? Những gì Im hỏi là một quyết định thiết kế hoặc một giới hạn lang? – NoSenseEtAl

+0

để rõ ràng, tôi biết họ có thể tạo mẫu với 2 tham số mẫu, nhưng Im tự hỏi nó sẽ xung đột với 1 mẫu phiên bản param – NoSenseEtAl

+0

@NoSenseEtAl, tôi sẽ nói quyết định thiết kế. Nó đơn giản hơn theo cách đó và tính toán khoảng cách giữa các trình vòng lặp của các loại khác nhau (nói, một trình vòng lặp truy cập ngẫu nhiên và một trình lặp chuyển tiếp) có lẽ không phải là thứ bạn muốn làm rất thường xuyên. Bạn thực sự có thể viết một phiên bản với hai đối số mẫu, nhưng vấn đề thực tế nào sẽ giải quyết được? –

3

std::distance sẽ làm việc với hai trình lặp đó không hoạt động là suy luận đối số mẫu. Trình biên dịch đang cố gắng giải quyết loại nào để thay thế cho đối số mẫu đầu tiên và có hai ứng cử viên tiềm năng, theo tiêu chuẩn kết thúc trong một thất bại.

Bạn có thể làm một trong hai điều, hoặc là so sánh chỉ lặp cùng loại, hoặc cung cấp các loại với mẫu:

std::distance<std::vector<int>::const_iterator>(v.begin(), v.cbegin()); 
4

Như mọi người đều biết, đó là vì std::distance chỉ mất một loại iterator, và việc khấu trừ đối số mẫu không thể chọn giá trị của nó (mặc dù chỉ có một trong số chúng là có thể cho rằng iterator chuyển đổi thành const_iterator nhưng không quay lại).

Nó có thể là giá trị văn bản mẫu một cái gì đó như thế này:

template <typename Container> 
typename Container::const_iterator constify(const Container &, typename Container::iterator it) { 
    return it; 
} 

Sau đó, bạn có thể buộc các mẫu trích như thế này:

std::distance(constify(v, it), cit); 

thay vì viết ra rằng loại dài tuyệt vời. Các tham số Container& là một sự xấu hổ, nó có bởi vì AFAIK Container không thể được suy luận từ một đối số iterator một mình.

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