Làm cách nào để tôi gõ một con trỏ hàm với cú pháp C ++ 11 bằng cách sử dụng cú pháp?


171

Tôi muốn viết cái này

typedef void (*FunctionPtr)();

sử dụng using. Làm thế nào tôi có thể làm điều đó?


2
usingthực sự rất khó hiểu , đặc biệt là vì các định danh con trỏ hàm thường nằm ở giữa typedefcâu lệnh và di chuyển ra phía trước bằng cách sử dụng using. Ít nhất đó là nơi tôi đã mất.
bắt đầu

Câu trả lời:


180

Nó có một cú pháp tương tự, ngoại trừ bạn loại bỏ định danh khỏi con trỏ:

using FunctionPtr = void (*)();

Đây là một ví dụ

Nếu bạn muốn "lấy đi sự xấu xí", hãy thử những gì Xeo gợi ý:

#include <type_traits>

using FunctionPtr = std::add_pointer<void()>::type;

Và đây là một bản demo khác .


25
Dang, tôi hy vọng nó sẽ lấy đi sự xấu xí:(
rubenvb

10
@rubenvb : using FunctionPtr = AddPointer<void()>;;)
Xèo

2
Bạn có thể sử dụng các bí danh loại mẫu để làm sạch thêm add_pointer<void()>::type: Sử dụng đề xuất tại đây: Groups.google.com/a/isocpp.org/d/msg/std-proposeals/xDQR3y5uTZ0/, bạn có thể viết pointer<function<void>>.
bames53

5
Các bí danh loại này thay đổi cú pháp loại từ tối nghĩa, cú pháp từ trong ra thành cú pháp từ trái sang phải đơn giản, điều này giúp loại bỏ phần lớn nhu cầu về typedefs tùy chỉnh cho các API cụ thể giúp viết các loại hợp chất của API dễ dàng hơn.
bames53

10
Trong C ++ 14, bạn sẽ có thể viết: bằng cách sử dụng FunctionPtr = std :: add_pulum_t <void ()>;
Andrzej

46

"Sự xấu xí" cũng có thể bị lấy đi nếu bạn tránh gõ con trỏ:

void f() {}
using Function_t = void();    
Function_t* ptr = f;
ptr();

http://ideone.com/e1XuYc


Đây là một cách tiếp cận thú vị, mặc dù tôi có thể lo lắng tôi sẽ quên *sau này và nhận được các lỗi khó hiểu.
Apollys hỗ trợ Monica

Đây chắc chắn là phiên bản đẹp nhất được trình bày ở đây. Cảm ơn bạn. Và tôi thích nhìn thấy một con trỏ, vì nó là một con trỏ hàm sau tất cả.
Pierre

13

Bạn muốn một type-id, về cơ bản giống hệt như một tuyên bố ngoại trừ bạn xóa declarator-id. Các declarator-idthường là một định danh, và tên bạn đang khai báo trong tờ khai equivilant.

Ví dụ:

int x

Các declarator-idđược xvì vậy chỉ cần loại bỏ nó:

int

Tương tự như vậy:

int x[10]

Xóa x:

int[10]

Ví dụ của bạn:

void (*FunctionPtr)()

Ở đây declarator-idFunctionPtr. Vì vậy, chỉ cần loại bỏ nó để có được type-id:

void (*)()

Điều này hoạt động vì được cung cấp, type-idbạn luôn có thể xác định duy nhất nơi định danh sẽ đi để tạo khai báo. Từ 8.1.1 trong tiêu chuẩn:

Có thể xác định duy nhất vị trí trong [loại id] nơi định danh sẽ xuất hiện nếu công trình là [khai báo]. Loại được đặt tên sau đó giống như loại định danh giả định.


9

Làm thế nào về cú pháp này cho rõ ràng? (Lưu ý dấu ngoặc kép)

void func();
using FunctionPtr = decltype((func));

1
Dấu ngoặc kép có nghĩa là gì trong bối cảnh này? Một tham chiếu đến một con trỏ hàm?
0x499602D2

5
Của bạn FunctionPtrkhông phải là một con trỏ hàm, nhưng decltype(&f)là, xem ở đây .
rubenvb

@ 1234597890 FunctionPtr là một tham chiếu giá trị không phải là hằng số để gõ 'void ()'
Leo Goodstadt

@rubenvb: Bạn nói đúng. Nó không phải là một con trỏ hàm mà là một tham chiếu giá trị cho hàm (kiểu). Đó là lý do tại sao static_assert thất bại ... <br/> Hãy thử sử dụng FunctionPtr: sử dụng không gian tên std; #include <iostream> void do_f () {cerr << "gì? \ n"; } void f (); sử dụng FunctionPtr = dectype ((f)); sử dụng FunctionPtr2 = dectype (& f); // Không hoạt động // sử dụng FunctionPtr3 = Dectype (f); int main () {FunctionPtr ff = do_f; ff (); HàmPtr2 ff2 = do_f; ff2 (); }
Leo Goodstadt

1

Một cách tiếp cận khác có thể sử dụng kiểu trả về tự động với kiểu trả về theo sau.

using FunctionPtr = auto (*)(int*) -> void;

Điều này có lợi thế có thể tranh cãi là có thể nói một cái gì đó là một hàm ptr khi bí danh bắt đầu bằng "auto (*)" và nó không bị xáo trộn bởi các tên định danh.

Đối chiếu

typedef someStructureWithAWeirdName& (FunctionPtr*)(type1*, type2**, type3<type4&>);

với

using FunctionPtr = auto (*)(type1*, type2**, type3<type4&>) -> someStructureWithAWeirdName&;

Tuyên bố miễn trừ trách nhiệm: Tôi đã lấy điều này từ bài nói chuyện "Dễ dàng vào C ++ hiện đại" của Bean Deane

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.