2012-02-07 49 views
6

Tôi muốn thực hiện các hoạt động tương tự trên nhiều mảng, một cái gì đó như:Lặp lại tham chiếu?

#include<vector> 
#include<algorithm> 
int main(void){ 
    std::vector<double> a, b; 
    for(auto& ab:{a,b}) std::sort(ab.begin(),ab.end()); // error 
} 

Mã này thất bại, kể từ auto& là một const tham chiếu. Có một cách thanh lịch xung quanh nó?

+1

là gì '{a, b} '? –

+2

@ Độ sáng là một 'std :: initializer_list >'. vấn đề ở đây là các trình lặp của một danh sách khởi tạo là * luôn luôn * 'const'. –

+0

Vì vậy, có bạn đi. Tôi tự hỏi liệu một số phép thuật chuyển tiếp rvalue có thể giúp đỡ ở đây không. –

Trả lời

7

Tôi nghĩ rằng vấn đề là nó giống như ràng buộc tạm thời với tham chiếu không phải const. Không có bộ sưu tập "cụ thể" ở đó nên nó hơi giống như tạm thời.

NẾU bạn có một véc tơ tạm thời ở đó, nó sẽ liên kết với tham chiếu const nhưng không liên kết với nhau.

Tôi cũng nghĩ rằng điều này sẽ không bao giờ làm việc gì bạn đang làm, nhưng điều này sẽ làm việc:

#include<vector> 
#include<algorithm> 
int main(void) 
{  
    std::vector<double> a, b;  
    for(std::vector<double>* ab:{&a,&b}) 
     std::sort(ab->begin(),ab->end()); // or begin(*ab),end(*ab) 
} 

và tự động có thể làm việc quá.

+0

Oh có con trỏ giải quyết nó một cách thanh lịch, cảm ơn.Và người ta có thể viết cả hai 'auto' và' auto * ':-) – eudoxos

+3

cảm giác tức thời của tôi về những gì bạn đang làm là ngay cả khi bạn có nó để biên dịch, bạn có thể sắp xếp các bản sao một cách hiệu quả. Đó là lý do tại sao bạn may mắn trong một cách mà trình biên dịch dừng lại bạn. – CashCow

+0

@CashCow: Chính xác, 'std :: initializer_list' tự động sao chép. – Xeo

2

Mã này không thành công, vì tự động & là tham chiếu const. [nhấn mạnh mỏ]

Lý do của bạn không giữ. Trong vòng lặp dựa trên phạm vi, những gì bạn khai báo (ở đây, auto& ab) là không phải được liên kết với biểu thức phạm vi (tại đây, {a,b }). Thay vào đó, ab sẽ được khởi tạo từ các yếu tố của phạm vi, không phải phạm vi của chính nó.

Thay vào đó, lỗi xuất phát từ việc gọi std::sort với thông số ab.begin()/ab.end(), có thể dễ dàng được chứng kiến ​​bằng cách nhận xét nội dung vòng lặp. Như RMartinho đã chỉ ra, các thành phần của std::initializer_list<std::vector<double>> là không thay đổi và bạn không thể sắp xếp vùng chứa const (std::sort các yếu tố bằng cách sử dụng di chuyển, không thể gán cho phần tử const).

Giả sử bạn muốn (độc lập) sắp xếp cả hai vectơ, bạn có thể làm:

for(auto& ab: { std::ref(a), std::ref(b) }) 
    std::sort(std::begin(ab.get()), std::end(ab.get())); 

ý rằng theo nguyên tắc khấu trừ mẫu đối số, auto& là tốt ở đây và auto sẽ được rút ra để const std::reference_wrapper<std::vector<double>>, năng suất std::reference_wrapper<std::vector<double>> const& như loại ab.

+0

Tôi đã suy nghĩ giống nhau: bạn không thể có một vector tham chiếu vì nó thiếu ngữ nghĩa nhưng một danh sách khởi tạo của std :: ref có thể làm việc tốt cho nó, trong trường hợp đó bạn sẽ không cần phải dereference các con trỏ như tôi đã làm. Tôi không chắc chắn bạn cần tự động &, tự động có thể làm tốt như get() là một thành viên const của một std :: ref. Cùng một cách mà tôi hoạt động như tôi có con trỏ const nhưng không trỏ đến const. – CashCow

+0

Đây có phải là tính năng đặc biệt của std :: ref không? Tại sao không được tự động suy ra để const std :: ref_t > và bạn có thể gọi std :: vector & get() const – CashCow

+0

@CashCow Lỗi của tôi, 'std :: vector ' doesn ' t có một thành viên 'get' và tôi đã thực sự muốn tham khảo' std :: reference_wrapper > '. Cảm ơn cho những người đứng đầu lên. –

0

Tôi nghĩ giải pháp CashCows rất hay. Chỉ để hiển thị một cách khác: Bạn cũng có thể sử dụng các mẫu variadic để giải quyết vấn đề này.

#include <vector> 
#include <algorithm> 

using namespace std; 

void mysort() {} // termination version 

template<typename Arg1, typename... Args> 
void mysort(Arg1 &arg1, Args&... args) 
{ 
    sort(arg1.begin(), arg1.end()); 
    mysort(args...); 
} 

int main(void) 
{ 
    vector<double> a, b; 
    mysort(a, b); 
} 

@CashCow: Có thể vượt qua một thuật toán như là đối số nhưng nó là một chút xấu xí vì việc sử dụng decltype:

#include <vector> 
#include <algorithm> 

using namespace std; 

template<typename Algo> 
void mysort(Algo algo) {} // termination version 

template<typename Algo, typename Arg1, typename... Args> 
void mysort(Algo algo, Arg1 &arg1, Args&... args) 
{ 
    algo(arg1.begin(), arg1.end()); 
    mysort(algo, args...); 
} 

int main(void) 
{ 
    vector<double> a, b; 
    mysort(&sort<decltype(a.begin())>, a, b); 
} 
+0

Tốt nhưng chúng tôi có thể thêm một lambda vào mẫu variadic của bạn cho phép chúng tôi đưa vào thuật toán mà chúng tôi muốn gọi, tức là sửa đổi sắp xếp thành bất kỳ thuật toán nào có phạm vi. Ngẫu nhiên không sắp xếp công việc bây giờ trên một phạm vi mà không cần phải xác định được và kết thúc? Thuật toán sẽ tự động gọi cho bạn. Tôi không thể làm điều đó trong giải pháp của tôi bởi vì nó có con trỏ. – CashCow

+0

@CashCow xem chỉnh sửa của tôi cho phiên bản có thuật toán làm tham số. – frast

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