Yay, một tiêu đề câu hỏi khác bao gồm một chuỗi ngẫu nhiên các thuật ngữ C++!Chức năng chuyển đổi theo khuôn mẫu thành con trỏ chức năng
Thông thường chúng tôi tạo một lớp Có thể gọi bằng cách triển khai operator()
. Nhưng bạn cũng có thể làm như vậy bằng cách thực hiện chuyển đổi do người dùng xác định để hoạt động con trỏ hoặc loại tham chiếu. Thay vì sử dụng chuyển tiếp hoàn hảo, một hàm chuyển đổi có thể trả về một con trỏ tới một hàm mà sau đó được gọi với danh sách đối số gốc.
struct call_printf {
typedef int printf_t(char const *, ...);
operator printf_t &() { return std::printf; }
};
Theo như tôi có thể nói, các typedef
trên là một điều cần thiết cú pháp. Tên của hàm chuyển đổi được tạo từ loại-specifier-seq, không cho phép cấu trúc như int (*)()
. Điều đó sẽ yêu cầu một người khai báo trừu tượng . Có lẽ lý do là các tên kiểu như vậy trở nên phức tạp và các cấu trúc phức tạp được sử dụng làm tên đối tượng khó phân tích cú pháp.
Chức năng chuyển đổi cũng được phép được tạo mẫu, nhưng các đối số mẫu phải được suy luận, vì không có nơi nào để chỉ định rõ chúng. (Điều đó sẽ đánh bại toàn bộ các điểm chuyển đổi ngầm.)
Câu hỏi # 1: Trong C++ 03, là không có cách nào để xác định một hàm operator chuyển đổi mẫu? Nó xuất hiện không có cách nào để giải quyết các đối số mẫu (tức là, đặt tên chúng trong một bối cảnh suy luận) trong một kiểu con trỏ hàm có thể chấp nhận được.
Dưới đây là tham chiếu tương đương từ C++ 11, §13.3.1.1.2/2 [over.call.object]. Đó là cơ bản giống từ C++ 03:
Bên cạnh đó, đối với mỗi chức năng chuyển đổi không rõ ràng tuyên bố trong T có dạng
operator conversion-type-id() cv-qualifier attribute-specifier-seqopt;
nơi cv-vòng loại là CV-cùng trình độ, hoặc bằng cv lớn hơn, cv, và nơi loại chuyển đổi-id biểu thị loại “con trỏ đến hàm (P1, ..., Pn) trở về R”, hoặc loại "Tham chiếu đến con trỏ đến hàm của (P1, ..., P n) trở R”, hoặc gõ‘tham chiếu đến chức năng (P1, ..., Pn) trở R’, một chức năng gọi thay thế với tên duy nhất gọi chức năng và có hình thức
R call-function (conversion-type-id F, P1 a1, ... ,Pn an) { return F (a1,... ,an); }
là cũng được coi là một chức năng ứng cử viên. Tương tự, các hàm gọi thay thế được thêm vào tập hợp các hàm ứng cử viên cho mỗi hàm chuyển đổi không rõ ràng được khai báo trong một lớp cơ sở của T cung cấp hàm không bị ẩn trong T bằng một tuyên bố can thiệp khác.
Câu hỏi # 2: Trong C++ 11, một sự chuyển đổi như vậy có thể được xác định bằng cách sử dụng mẫu đối số mặc định? Điều này rất hữu ích cho SFINAE. Sự khác biệt duy nhất ở đây từ ví dụ trên là loại chuyển đổi-id chỉ đại diện cho tham chiếu hàm sau khi khởi tạo, bởi vì đó là loại phụ thuộc (bất chấp sự bất biến).Điều này đi lên GCC và nó bỏ qua mẫu thành viên.
enum { call_alternate = true; }
struct call_switch {
template< bool en = call_alternate >
operator typename std::enable_if< en, decltype(fn_1) & >::type()
{ return fn_1; }
template< bool en = ! call_alternate >
operator typename std::enable_if< en, decltype(fn_2) & >::type()
{ return fn_2; }
};
Chúng tôi cũng có các mẫu bí danh. Có vẻ như thay thế bí danh xảy ra trước khi diễn giải, được đưa ra ví dụ trong §14.5.7/2, trong đó các tuyên bố của cuộc xung đột process
. Trong GCC 4.7, mã này ít nhất là instantiates khai báo, nhưng sau đó nó tạo ra một kỳ lạ "ứng cử viên mong đợi 2 đối số, 2 cung cấp" lỗi.
template< typename t >
using fn_t = void (&)(t);
struct talk {
template< typename t >
operator fn_t<t>() { return fn; }
};
int main() {
talk()(3);
}
Lòng tốt của tôi .... –
Bạn đang cố gắng làm gì? Nó có thể hữu ích ở đâu? – Nawaz
@Nawaz khi bạn muốn toán tử chuyển đổi hoạt động các loại con trỏ? –