ฉันจะพิมพ์ตัวชี้ฟังก์ชันด้วย C ++ 11 โดยใช้ไวยากรณ์ได้อย่างไร


171

ฉันต้องการเขียนสิ่งนี้

typedef void (*FunctionPtr)();

usingการใช้ ฉันจะทำอย่างไร


2
มาก conf usingแน่นอนโดยเฉพาะอย่างยิ่งเพราะตัวระบุชี้ทำงานมักจะอาศัยอยู่ในช่วงกลางของการให้คำสั่งและย้ายไปด้านหน้าใช้typedef usingอย่างน้อยนั่นคือสิ่งที่ฉันหลงทาง
starturtle

คำตอบ:


180

มันมีไวยากรณ์ที่คล้ายกันยกเว้นคุณลบตัวระบุจากตัวชี้:

using FunctionPtr = void (*)();

นี่คือตัวอย่าง

หากคุณต้องการ "กำจัดความอัปลักษณ์" ลองสิ่งที่ Xeo แนะนำ:

#include <type_traits>

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

และนี่ก็เป็นอีกหนึ่งการสาธิต


25
แดงฉันหวังว่ามันจะนำความอัปลักษณ์ออกไป:(
rubenvb

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

2
เป็นไปได้ที่จะใช้นามแฝงประเภทเทมเพลตเพื่อล้างข้อมูลเพิ่มเติมadd_pointer<void()>::type: ใช้คำแนะนำที่นี่: groups.google.com/a/isocpp.org/d/msg/std-proposals/xDQR3y5uTZ0/คุณสามารถเขียนpointer<function<void>>ได้
bames53

5
นามแฝงประเภทเหล่านี้เปลี่ยนไวยากรณ์ประเภทจากคลุมเครือ, ไวยากรณ์ภายในออกเป็นไวยากรณ์ซ้ายไปขวาง่ายซึ่งส่วนใหญ่ไม่จำเป็นต้องพิมพ์ที่กำหนดเองสำหรับ API เฉพาะที่ทำให้ง่ายต่อการเขียนประเภทสารประกอบของ API ที่
bames53

10
ใน C ++ 14 คุณจะสามารถเขียน: using FunctionPtr = std :: add_pointer_t <void ()>;
Andrzej

46

"ความอัปลักษณ์" สามารถนำไปได้หากคุณหลีกเลี่ยงการพิมพ์ตัวชี้:

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

http://ideone.com/e1XuYc


นี่เป็นวิธีที่น่าสนใจแม้ว่าฉันอาจกังวลว่าฉันจะลืมใน*ภายหลังและได้รับข้อผิดพลาดที่ทำให้สับสน
Apollys รองรับ Monica

นี่เป็นรุ่นที่อร่อยที่สุดที่นำเสนอที่นี่อย่างแน่นอน ขอบคุณ. และฉันชอบเห็นตัวชี้เพราะมันเป็นตัวชี้ฟังก์ชั่นหลังจากทั้งหมด
ปิแอร์

13

คุณต้องการซึ่งเป็นหลักเหมือนกับการประกาศยกเว้นคุณลบtype-id declarator-idโดยdeclarator-idปกติจะเป็นตัวระบุและชื่อที่คุณประกาศในการประกาศอย่างเท่าเทียมกัน

ตัวอย่างเช่น:

int x

declarator-idเป็นxดังนั้นเพียงแค่ลบออก:

int

ในทำนองเดียวกัน:

int x[10]

ลบx:

int[10]

สำหรับตัวอย่างของคุณ:

void (*FunctionPtr)()

ที่นี่คือdeclarator-id FunctionPtrดังนั้นเพียงแค่ลบออกเพื่อรับtype-id:

void (*)()

งานนี้ได้รับเนื่องจากtype-idคุณสามารถกำหนดเฉพาะที่ตัวระบุจะไปสร้างการประกาศ จาก 8.1.1 ในมาตรฐาน:

เป็นไปได้ที่จะระบุตำแหน่งโดยเฉพาะใน [type-id] ที่ตัวระบุจะปรากฏขึ้นหากการก่อสร้างเป็น [ประกาศ] ประเภทที่มีชื่อนั้นจะเหมือนกับชนิดของตัวระบุสมมุติฐาน


9

ไวยากรณ์นี้เกี่ยวกับความชัดเจนอย่างไร (หมายเหตุวงเล็บคู่)

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

1
เครื่องหมายวงเล็บคู่หมายถึงอะไรในบริบทนี้ การอ้างอิงถึงตัวชี้ฟังก์ชั่น?
0x499602D2

5
คุณFunctionPtrไม่ได้เป็นตัวชี้ฟังก์ชัน แต่decltype(&f)จะดูที่นี่
rubenvb

@ 1234597890 FunctionPtr เป็นการอ้างอิง lvalue ที่ไม่ใช่แบบ const เพื่อพิมพ์ 'void ()'
Leo Goodstadt

@rubenvb: คุณพูดถูก มันไม่ใช่ตัวชี้ฟังก์ชัน แต่เป็นการอ้างอิง lvalue กับฟังก์ชัน (ชนิด) ซึ่งเป็นสาเหตุที่ static_assert ล้มเหลว ... <br/> ลองใช้ FunctionPtr: using namespace std; #include <iostream> เป็นโมฆะ do_f () {cerr << "what? \ n"; } ถือเป็นโมฆะ f (); ใช้ FunctionPtr = decltype ((f)); ใช้ FunctionPtr2 = decltype (& f); // ไม่ทำงาน // ใช้ FunctionPtr3 = decltype (f); int main () {FunctionPtr ff = do_f; ff (); FunctionPtr2 ff2 = do_f; FF2 (); }
Leo Goodstadt

1

วิธีการอื่นอาจใช้ชนิดการคืนอัตโนมัติพร้อมชนิดการคืนกลับมา

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

นี่เป็นข้อได้เปรียบที่พิสูจน์ได้ว่าสามารถบอกบางสิ่งได้ว่าเป็นฟังก์ชั่น ptr เมื่อนามแฝงเริ่มต้นด้วย "auto (*)" และไม่ได้ทำให้งงงวยโดยชื่อตัวระบุ

เปรียบเทียบ

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

กับ

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

คำแถลงการณ์ปฏิเสธความรับผิดชอบ: ฉันนำสิ่งนี้มาจากการพูดคุยของ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.