Bagaimana cara saya mengetik pointer fungsi dengan C ++ 11 menggunakan sintaks?


171

Saya ingin menulis ini

typedef void (*FunctionPtr)();

menggunakan using. Bagaimana saya melakukannya?


2
sangat conf usingmemang, terutama karena pengidentifikasi fungsi pointer biasanya berada di tengah typedefpernyataan dan pindah ke depan menggunakan using. Setidaknya di situlah aku tersesat.
— starturtle

Jawaban:


180

Ini memiliki sintaks yang sama, kecuali Anda menghapus pengidentifikasi dari pointer:

using FunctionPtr = void (*)();

Ini sebuah contoh

Jika Anda ingin "menghilangkan keburukan", coba apa yang disarankan Xeo:

#include <type_traits>

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

Dan ini demo lain .


25
Sial, saya berharap itu akan menghilangkan keburukan:(
— rubenvb

10
@rubenvb:; using FunctionPtr = AddPointer<void()>;)
— Xeo

2
Dimungkinkan untuk menggunakan alias tipe templat untuk membersihkan lebih lanjut add_pointer<void()>::type: Menggunakan saran di sini: groups.google.com/a/isocpp.org/d/msg/std-proposals/xDQR3y5uTZ0/… Anda dapat menulis pointer<function<void>>.
— bames53

5
Alias ​​tipe ini mengubah sintaksis tipe dari sintaksis tidak jelas, dalam-ke luar menjadi sintaksis kiri-ke-kanan yang sederhana, yang sebagian besar menghilangkan kebutuhan akan typedef khusus untuk API tertentu yang membuatnya lebih mudah untuk menulis tipe majemuk API itu.
— bames53

10
Di C ++ 14, Anda akan dapat menulis: menggunakan FunctionPtr = std :: add_pointer_t <void ()>;
— Andrzej

46

"Keburukan" juga dapat dihapus jika Anda menghindari mengetikkan pointer:

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

http://ideone.com/e1XuYc


Ini adalah pendekatan yang menarik, meskipun saya mungkin khawatir saya akan melupakannya *nanti dan mendapatkan kesalahan yang membingungkan.
— Apollys mendukung Monica

Ini jelas merupakan versi terbaik yang disajikan di sini. Terima kasih. Dan saya lebih suka melihat pointer, karena itu adalah pointer fungsi.
— Pierre

13

Anda menginginkan type-id, yang pada dasarnya sama persis dengan deklarasi kecuali Anda menghapus declarator-id. The declarator-idbiasanya merupakan identifier, dan nama Anda menyatakan dalam deklarasi equivilant.

Sebagai contoh:

int x

The declarator-idadalah xjadi hanya menghapusnya:

int

Juga:

int x[10]

Hapus x:

int[10]

Sebagai contoh Anda:

void (*FunctionPtr)()

Di sini declarator-idadalah FunctionPtr. jadi hapus saja untuk mendapatkan type-id:

void (*)()

Ini berfungsi karena diberikan type-idAnda selalu dapat menentukan secara unik ke mana pengenal akan pergi untuk membuat deklarasi. Dari 8.1.1 dalam standar:

Dimungkinkan untuk mengidentifikasi secara unik lokasi di [type-id] tempat pengidentifikasi akan muncul jika konstruksi adalah [deklarasi]. Jenis yang dinamai ini kemudian sama dengan jenis pengenal hipotetis.


9

Bagaimana dengan sintaks ini untuk kejelasan? (Catatan kurung ganda)

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

1
Apa arti tanda kurung ganda dalam konteks ini? Sebuah referensi untuk fungsi pointer?
— 0x499602D2

5
Anda FunctionPtrbukan penunjuk fungsi, tetapi decltype(&f), lihat di sini .
— rubenvb

@ 1234597890 FunctionPtr adalah referensi nilai non-const untuk mengetikkan 'void ()'
— Leo Goodstadt

@rubenvb: Anda benar. Ini bukan penunjuk fungsi tetapi referensi nilai untuk fungsi (tipe). Karena itulah static_assert gagal ... <br/> Coba gunakan FunctionPtr: using namespace std; #include <iostream> void do_f () {cerr << "what? \ n"; } membatalkan f (); menggunakan FunctionPtr = decltype ((f)); menggunakan FunctionPtr2 = decltype (& f); // Tidak berfungsi // menggunakan FunctionPtr3 = decltype (f); int main () {FunctionPtr ff = do_f; ff (); FunctionPtr2 ff2 = do_f; ff2 (); }
— Leo Goodstadt

1

Pendekatan lain mungkin menggunakan tipe pengembalian otomatis dengan tipe penelusuran belakang.

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

Ini memiliki keunggulan yang dapat diperdebatkan untuk dapat mengatakan sesuatu adalah fungsi ptr ketika alias dimulai dengan "auto (*)" dan tidak dikaburkan oleh nama pengenal.

Membandingkan

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

dengan

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

Penafian: Saya mengambil ini dari pembicaraan "Easing into Modern C ++" Bean Deane

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.