Sözdizimini kullanarak C ++ 11 ile bir işlev işaretçisini nasıl tanımlayabilirim?


171

Bunu yazmak istiyorum

typedef void (*FunctionPtr)();

kullanarak using. Bunu nasıl yaparım?


2
Çok konf usinggerçekten işlev işaretçisi tanımlayıcıları genellikle ortasında ikamet özellikle çünkü typedefkullanılarak ön tablosu ve hareket using. En azından kaybolduğum yer burası.
starturtle

Yanıtlar:


180

İşaretçiyi tanıtıcıdan kaldırmanız dışında benzer bir sözdizimi vardır:

using FunctionPtr = void (*)();

İşte bir örnek

"Çirkinliği ortadan kaldırmak" istiyorsanız, Xeo'nun önerisini deneyin:

#include <type_traits>

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

Ve işte bir başka demo daha .


25
Dang, çirkinliği götüreceğini umdum:(
rubenvb

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

2
Daha fazla temizlemek için şablon türü takma adları kullanmak mümkündür add_pointer<void()>::type: Buradaki öneriyi kullanarak: groups.google.com/a/isocpp.org/d/msg/std-proposals/xDQR3y5uTZ0/… yazabilirsiniz pointer<function<void>>.
bames53

5
Bu tür takma adları, tür sözdizimini belirsiz, içten dışa sözdiziminden basit bir soldan sağa sözdizimine dönüştürür; bu, söz konusu API'nın bileşik türlerini yazmayı kolaylaştıran belirli API'ler için özel typedefs ihtiyacını büyük ölçüde ortadan kaldırır.
bames53

10
C ++ 14'te şunu yazabilirsiniz: FunctionPtr = std :: add_pointer_t <void ()>;
Andrzej

46

Bir işaretçi tanımlamaktan kaçınırsanız, "çirkinlik" de kaldırılabilir:

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

http://ideone.com/e1XuYc


Bu ilginç bir yaklaşım, ancak *daha sonra unutacağım ve kafa karıştırıcı hatalar alacağımdan endişelenebilirim .
Apollys,

Bu kesinlikle burada sunulan en güzel sürümüdür. Teşekkür ederim. Ve sonuçta bir işlev işaretçisi olduğu için bir işaretçi görmeyi tercih ederim.
Pierre

13

Eğer type-idsilmek dışında bir bildirim ile tam olarak aynı olan bir , istiyorum declarator-id. declarator-idGenellikle bir tanımlayıcı ve ad equivilant bildiriminde beyan edilmektedir.

Örneğin:

int x

declarator-idOlduğu xyani sadece kaldırın:

int

Aynı şekilde:

int x[10]

Şunları çıkarın x:

int[10]

Örneğiniz için:

void (*FunctionPtr)()

İşte declarator-idbir FunctionPtr. bu yüzden almak için kaldırın type-id:

void (*)()

Bu işe yarar çünkü verilen type-idher zaman tanımlayıcının bir bildirim oluşturmak için nereye gideceğini benzersiz bir şekilde belirleyebilirsiniz. Standartta 8.1.1'den:

[Type-id] öğesinde, yapı bir [bildirim] olsaydı tanımlayıcının görüneceği yeri benzersiz bir şekilde tanımlamak mümkündür. Adlandırılmış tür daha sonra varsayımsal tanımlayıcının türüyle aynıdır.


9

Netlik için bu sözdizimine ne dersiniz? (Çift parantez not alın)

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

1
Bu bağlamda çift parantez ne anlama geliyor? Bir işlev işaretçisine başvuru ?
0x499602D2

5
Sizin FunctionPtrbir işlev işaretçisi değil, ama burayadecltype(&f) bakın .
rubenvb

@ 1234597890 FunctionPtr, 'void ()' türüne const olmayan bir değer referansıdır
Leo Goodstadt

@rubenvb: Haklısın. Bu bir işlev işaretçisi değil, işleve (tip) yönelik bir değer referansıdır. Bu nedenle static_assert başarısız oluyor ... <br/> FunctionPtr kullanmayı deneyin: namespace std; #include <iostream> void do_f () {cerr << "ne? \ n"; } void f (); FunctionPtr = decltype ((f)) kullanarak; FunctionPtr2 = decltype (& f) kullanarak; // Çalışmıyor // FunctionPtr3 = decltype (f) kullanarak; int main () {FunctionPtr ff = do_f; ff (); FunctionPtr2 ff2 = do_f; FF2 (); }
Leo Goodstadt

1

Başka bir yaklaşım, otomatik dönüş türünü takip eden dönüş türüyle kullanabilir.

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

Bu, takma ad "auto (*)" ile başladığında ve tanımlayıcı adları tarafından gizlenmediğinde, bir şeyin ptr işlevi olduğunu söyleyebilme avantajına sahiptir.

Karşılaştırmak

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

ile

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

Feragatname: Bean Deane'nin "Easing into Modern C ++" konuşmasından aldım

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.