2014-10-17 21 views
5

Tôi đã xem qua đoạn mã sau:Loại "char (& (...)) [2]" có nghĩa là gì?

char (&f(...))[2];

Tôi đã kiểm tra các loại của nó (sử dụng typeid và C++ filt) và nhận được:

char (&(...)) [2]

Nhưng tôi không thể hiểu rõ loại này. [2] là phần ném tôi đi. Nếu không có nó, tôi có thể sao chép các loại trong một định nghĩa chức năng, ví dụ:

char (&f(...))

f là cùng loại như h trong (ít nhất là từ đầu ra của typeid + C++ filt):

char& h(...)

+0

Vui lòng đăng toàn bộ ngữ cảnh trong đó mã này xuất hiện. –

+0

không phải là nó tham chiếu đến mảng của 2 hàm trả về char và lấy hình elip kiểu C? – Creris

+3

Đó là một hàm trả về tham chiếu đến một mảng gồm hai ký tự. Cái thứ hai ('char (& f (...))') là một hàm trả về một tham chiếu đến một ký tự. Dấu ngoặc ngoài là thừa trong trường hợp thứ hai và trong cả hai trường hợp '...' là một gói đối số C variadic. – 0x499602D2

Trả lời

3

đó là một tuyên bố chức năng đã số các thông số khác nhau và trả về một tham chiếu đến một mảng nhân vật của hai yếu tố này.

Nó có thể được khai báo đơn giản hơn bằng cách sử dụng typedef. Ví dụ

typedef char char_array[2]; 

char_array & f(...); 
2

Bạn có thể sử dụng cdecl và thay thế một kiểu bất kỳ cho hình elip, như int:

char (&f(int)) [2] 

Dẫn đến

tuyên bố f như chức năng (int) trở về tài liệu tham khảo thành mảng 2 của char […]

Thay thế lại và bạn có tuyên bố của bạn bằng lời.

2
char (&f(...))[2]; 

Đây là khai báo hàm trả về tham chiếu đến một mảng gồm hai ký tự. Dấu ngoặc đơn là cần thiết cho điều này để được cú pháp chính xác. Nếu không, & sẽ liên kết với char và sẽ có lỗi cú pháp do [2] là vô nghĩa.

Cú pháp có thể bị phân tách bằng bí danh loại. Ví dụ:

using array_ref = char (&)[2]; 
array_ref f(...); 

Lý do trả về tham chiếu đến mảng chứ không phải mảng thực tế là do không thể trả về mảng. Điều đó là không thể. Bạn chỉ có thể trả lại các tham chiếu hoặc các con trỏ tới các mảng, giống như các hàm.

Trong tất cả các ví dụ, ... là C variadic argument pack.


Nơi duy nhất tôi thấy loại cú pháp này được sử dụng như một phần của độ phân giải quá tải chức năng cho SFINAE. Thông thường, hàm này đi kèm với tình trạng quá tải cùng tên sử dụng thay thế mẫu để kiểm tra thuộc tính của một kiểu nhất định.Nếu một sự thất bại thay thế xảy ra quá tải thứ hai (một trong đó có một gói variadic) được chọn làm dự phòng. Kiểu trả về của nó là điều phân biệt thành công hay thất bại.

Ví dụ, đây là lớp học đặc điểm để kiểm tra nếu một loại có một chức năng thành viên f():

template <typename T> 
struct has_f 
{ 
private: 
    using true_type = char (&)[1]; 
    using false_type = char (&)[2]; 

    template <typename U> 
    static decltype(std::declval<U>().f(), true_type()) f(int); 

    template <typename> 
    static false_type f(...); 
public: 
    static constexpr bool value = sizeof(check<T>(0)) == 1; 
}; 

Như bạn có thể thấy, nếu T có một hàm thành viên f(), sau đó kích thước của các loại trở lại sẽ 1, nếu không 2. true_typefalse_type phần lớn được thay thế bởi các lớp đặc điểm tiêu chuẩn std::true_typestd::false_type những ngày này, nhưng đây chỉ đơn giản là một ví dụ minh họa việc sử dụng nó.