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

171

Saya ingin menulis ini

typedef void (*FunctionPtr)();

menggunakan using. Bagaimana saya melakukannya?

rubenvb
sumber
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 .

0x499602D2
sumber
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

Vadim Goryunov
sumber
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.

Andrew Tomazos
sumber
9

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

void func();
using FunctionPtr = decltype((func));
Leo Goodstadt
sumber
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

Silvester
sumber