2010-10-19 37 views
20

Câu hỏi của tôi chắc chắn là một câu hỏi đơn giản cho bất kỳ ai quen thuộc với cú pháp C++. Tôi chỉ đang học C++ và đây là một số bài tập về nhà .Cách lấy kiểu giá trị từ trình lặp trong C++?

template<typename Iter> 
void quickSort(Iter begin, Iter end) 
{   
    //.. 
    auto pivot = * (begin + (end - begin)/2); 
    //.. 
} 

trục được cho là chứa giá trị từ tâm của khoảng [bắt đầu, kết thúc]. Ite Mã tôi đã viết ở đó hoạt động, nhưng auto là một từ khóa từ tiêu chuẩn mới của ngôn ngữ. Làm thế nào để làm điều đó theo cách cũ? Viết gì thay vì auto?

+18

Đó là những gì tôi muốn xem. Một người chỉ học C++, sử dụng trình lặp và 'tự động'. :) – jalf

Trả lời

23

typename std::iterator_traits<Iter>::value_type

Điều này sẽ có tác dụng nếu mẫu của bạn được khởi tạo với Iter như một loại con trỏ.

Nhân tiện, typename không phải là một phần của chính loại đó. Nó cho trình biên dịch biết rằng value_type thực sự là một kiểu. Nếu đó là tên của một hàm hoặc một thành viên dữ liệu tĩnh thì điều đó sẽ ảnh hưởng đến cú pháp. Trình biên dịch không nhất thiết phải biết nó là gì, vì việc chuyên môn hóa iterator_traits cho Iter có thể không hiển thị khi mẫu được biên dịch.

+1

Đây là giải pháp tốt nhất có thể, nhưng điều đáng nói là đây không phải là giải pháp chung. Nó không được đảm bảo để làm việc với mọi thứ mà người dùng có thể cố gắng truyền vào như một trình lặp (iterator) ... họ vẫn có thể cần thêm giá trị value_type vào đối tượng iterator của họ (hoặc tạo ra một chuyên môn cho các đặc điểm). Một cách thay thế chỉ đơn giản là tiếp tục sử dụng các trình vòng lặp và tạo một trình vòng lặp cho trục xoay, dereferencing nó khi cần, mà không cần loại giá trị bên trong hàm templated. –

+3

@ Tony: đó là sự thật, và 'auto' là tốt hơn cho lý do đó. Tuy nhiên, tất cả các thuật toán chuẩn yêu cầu người dùng truyền một cái gì đó có 'iterator_traits' (24.3.1), và nó hợp lý cho các mẫu hàm do người dùng định nghĩa để có cùng giới hạn. Những người viết vòng lặp có thể sử dụng 'std :: iterator' làm lớp cơ sở để thu hẹp khoảng cách giữa * cố gắng * để vượt qua trong một trình lặp, và thực sự truyền vào trong một' Iterator' ;-) –

+1

@Steve: có, tuyệt đối (và bạn đã nhận được +1 từ tôi rồi). –

1

Câu trả lời của Steve là đúng; trong C++ 98, bạn phải sử dụng std :: iterator_traits hoặc bạn có thể sử dụng Iter :: value_type nếu bạn biết rằng trình lặp có typedef này (ví dụ: bắt nguồn từ std :: iterator). Tuy nhiên, có một vấn đề khác trong mã của bạn: bạn thường không thể chỉ đơn giản là phân chia vòng lặp. Điều này làm việc với con trỏ, tất nhiên, nhưng không phải trong trường hợp tổng quát hơn. Một cách tiếp cận tổng quát hơn sẽ là:

Iter itPivot = std::advance(begin, std::distance(begin, end)/2); 
+0

Mã gốc không phân chia các trình lặp và điều này sẽ không hoạt động, ngay cả với con trỏ. Mã thay vì sử dụng phép trừ, hoạt động trên tất cả các trình vòng lặp truy cập ngẫu nhiên (không chỉ con trỏ). Và kể từ khi quicksort sẽ được sắp xếp cho các loại iterator khác anyway (một thực hiện hiệu quả anyway), việc sử dụng 'operator -' ở đây là tốt. –

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