2017-06-29 16 views
6

Để tránh nhầm lẫn, tôi hiểu rõ sự khác biệt giữa mảng và con trỏ, khái niệm phân rã thành con trỏ và khái niệm truyền mảng theo tham khảo trong C++ vvQuy tắc ràng buộc đối số hàm để truyền mảng bằng tham chiếu vs con trỏ ngang

câu hỏi của tôi ở đây là đặc biệt về các quy tắc sử dụng bởi trình biên dịch để chọn một chức năng từ một tập hợp các chức năng quá tải ứng cử viên, khi một tình trạng quá tải mất một tham chiếu mảng, và người kia quá tải mất một con trỏ.

Ví dụ, giả sử chúng ta có:

template <class T, std::size_t N> 
void foo(const T (&arr)[N]) 
{ 
    std::cout << "Array-reference overload!" << std::endl; 
} 

template <class T> 
void foo(const T* ptr) 
{ 
    std::cout << "Pointer overload!" << std::endl; 
} 

Nếu chúng ta cố gắng để gọi hàm mẫu foo() như sau:

const char arr[2] = "A"; 
foo(arr); 

... sau đó mong đợi của tôi sẽ là những đầu tiên quá tải, một trong đó có một tham chiếu mảng, sẽ được lựa chọn bởi trình biên dịch.

Tuy nhiên, sử dụng GCC 4.9.2, nếu tôi biên dịch mã ở trên, tôi nhận được một lỗi:

test.cpp:28:9: error: call of overloaded ‘foo(const char [2])’ is ambiguous 

Đó là chưa rõ ràng với tôi lý do tại sao cả hai quá tải được coi là ứng cử viên đều tốt bởi trình biên dịch ở đây, kể từ khi quá tải đầu tiên phù hợp với loại chính xác, trong khi quá tải thứ hai đòi hỏi một bước phân rã thêm con trỏ thêm.

Bây giờ, tôi có thể có được tình trạng quá tải ở trên làm việc bằng cách sử dụng một cách rõ ràng type_traits như sau:

template <class T, std::size_t N> 
void foo(const T (&arr)[N]) 
{ 
    std::cout << "Array-reference overload!" << std::endl; 
} 

template <class T> 
void foo(T ptr, typename std::enable_if<std::is_pointer<T>::value>::type* = 0) 
{ 
    std::cout << "Pointer overload!" << std::endl; 
} 

Trong trường hợp này, chương trình biên dịch và sự quá tải mà phải mất một mảng tham chiếu được chọn. Tuy nhiên, tôi không hiểu tại sao giải pháp này lại cần thiết. Tôi muốn hiểu lý do tại sao trình biên dịch xem xét một hàm yêu cầu phân rã-to-con trỏ một ứng cử viên có khả năng quá tải giống như tham chiếu mảng, khi đối số truyền vào là rất nhiều mảng.

Trả lời

4

the first overload matches the type exactly, whereas the second overload requires an extra decay-to-pointer step.

Bởi vì khi kiểm tra ranking of implicit conversion sequences trong overload resolution, các array-to-pointer conversion được coi là một kết hợp chính xác, do đó tình trạng quá tải 2 có cấp bậc tương tự với một 1st.

Từ tiêu chuẩn, $16.3.3.1.1 Standard conversion sequences [over.ics.scs] Table 13 — Conversions

Conversion     Category    Rank   Subclause 
No conversions required  Identity    Exact Match 
... ... 
Array-to-pointer conversion Lvalue Transformation Exact Match [conv.array] 
... ... 

Nó đáng chú ý là cấp bậc "Không có chuyển đổi bắt buộc" (ví dụ trường hợp của tình trạng quá tải 1st) là "Exact Match" quá.

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