ผ่านตัวชี้ฟังก์ชั่นจากอาร์เรย์ของตัวชี้ฟังก์ชั่นเป็นอาร์กิวเมนต์แม่แบบ


9

ฉันต้องการผ่านตัวชี้ฟังก์ชั่นจากอาร์เรย์ของตัวชี้ฟังก์ชั่นเป็นอาร์กิวเมนต์แม่แบบ รหัสของฉันดูเหมือนว่าจะรวบรวมโดยใช้ MSVC แม้ว่า Intellisense บ่นว่ามีบางอย่างผิดปกติ ทั้ง gcc และ clang ไม่สามารถคอมไพล์โค้ดได้

ลองพิจารณาตัวอย่างต่อไปนี้:

static void test() {}

using FunctionPointer = void(*)();

static constexpr FunctionPointer functions[] = { test };

template <FunctionPointer function>
static void wrapper_function()
{
    function();
}

int main()
{
    test();  // OK
    functions[0]();  // OK

    wrapper_function<test>();  // OK
    wrapper_function<functions[0]>();  // Error?
}

MSVCรวบรวมรหัส แต่ Intellisense ให้ข้อผิดพลาดดังต่อไปนี้:invalid nontype template argument of type "const FunctionPointer"

gccไม่สามารถคอมไพล์ด้วยข้อความต่อไปนี้:

<source>: In function 'int main()':
<source>:19:33: error: no matching function for call to 'wrapper_function<functions[0]>()'
   19 |  wrapper_function<functions[0]>();  // Error?
      |                                 ^
<source>:8:13: note: candidate: 'template<void (* function)()> void wrapper_function()'
    8 | static void wrapper_function()
      |             ^~~~~~~~~~~~~~~~
<source>:8:13: note:   template argument deduction/substitution failed:
<source>:19:30: error: '(FunctionPointer)functions[0]' is not a valid template argument for type 'void (*)()'
   19 |  wrapper_function<functions[0]>();  // Error?
      |                   ~~~~~~~~~~~^
<source>:19:30: note: it must be the address of a function with external linkage

เสียงดังกราวล้มเหลวในการรวบรวมกับข้อความต่อไปนี้:

<source>:19:2: error: no matching function for call to 'wrapper_function'
        wrapper_function<functions[0]>();  // Error?
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:8:13: note: candidate template ignored: invalid explicitly-specified argument for template parameter 'function'
static void wrapper_function()
            ^
1 error generated.

คำถาม:

คือwrapper_function<functions[0]>();ถูกต้องหรือไม่?

หากไม่เป็นเช่นนั้นมีสิ่งใดบ้างที่ฉันสามารถทำเพื่อส่งผ่านfunctions[0]อาร์กิวเมนต์แม่แบบไปได้wrapper_functionหรือไม่ { wrapper_function<functions[0]>, ..., wrapper_function<functions[std::size(functions) - 1]> }เป้าหมายของฉันคือการสร้างอาร์เรย์ใหม่ของตัวชี้ฟังก์ชั่นที่รวบรวมเวลากับเนื้อหา


อืมน่าสนใจฉันคิดว่าปัญหาคือคุณใช้ค่า (ตัวชี้) แทนประเภท แต่ก็wrapper_function<decltype(functions[0])>()ไม่ได้รวบรวม
CoryKramer

6
ดูเหมือนว่าจะทำงานใน C ++ 17 ... ตอนนี้เพื่อค้นหาความแตกต่างในมาตรฐาน ...
AndyG

คำตอบ:


5

wrapper_function<functions[0]>();ห้ามใช้นิพจน์เนื่องจากสิ่งต่อไปนี้:

14.3.2 แม่แบบที่ไม่ใช่ข้อโต้แย้งประเภท [temp.arg.nontype]

เท็มเพลตอาร์กิวเมนต์สำหรับพารามิเตอร์ที่ไม่ใช่ประเภทและไม่ใช่เท็มเพลตจะต้องเป็นหนึ่งใน:

[ ... ]

- นิพจน์คงที่ (5.19) ที่กำหนดที่อยู่ของวัตถุที่มีการจัดเก็บข้อมูลคงที่> ระยะเวลาและการเชื่อมโยงภายนอกหรือภายในหรือฟังก์ชั่นที่มีการเชื่อมโยงภายนอกหรือภายในรวมถึงฟังก์ชั่นแม่แบบและฟังก์ชั่น (ละเว้นเครื่องหมายวงเล็บ) เป็น & id-expression ยกเว้นว่า & อาจถูกละเว้นหากชื่ออ้างถึงฟังก์ชันหรืออาร์เรย์และจะถูกละเว้นหากเทมเพลตพารามิเตอร์ที่สอดคล้องกันนั้นเป็นข้อมูลอ้างอิง [ ... ]

ห้ามมิให้ใช้พอยน์เตอร์เป็นอาร์กิวเมนต์เท็มเพลตที่ไม่ใช่ชนิดอื่นนอกเหนือจากฟอร์ม&idดังนั้นโดยทั่วไปการติดตามจะทำงาน:

static void test() {}

using FunctionPointer = void(*)();

static constexpr FunctionPointer functions[] = { test };

template <FunctionPointer function>
static void wrapper_function()
{
    function();
}

int main()
{
    test();  // OK
    functions[0]();  // OK

    wrapper_function<test>();  // OK
    wrapper_function<&test>();  // OK
}

และตัวอย่างข้อมูลต่อไปนี้จะไม่ทำงานเมื่อรวบรวมด้วยตัวเลือก C ++ 14:

constexpr auto func = &test;
wrapper_function<func>();

เมื่อคอมไพล์ด้วยตัวเลือก C ++ 17 แนวทางของคุณและแนวทางด้านบนทั้งสองจะทำงานได้:

int main()
{
    test();  // OK
    functions[0]();  // OK

    wrapper_function<test>();  // OK
    wrapper_function<&test>();  // OK
    wrapper_function<func>();  // OK

    wrapper_function<functions[0]>();  // OK
}

ดูการถ่ายทอดสด


ไม่เพียง แต่รูปแบบ&idแต่ยังidได้รับอนุญาตสำหรับฟังก์ชั่นในขณะที่คุณแสดงให้เห็นในตัวอย่างและค่าตัวชี้โมฆะได้รับอนุญาตอย่างชัดเจนในรูปแบบการแสดงออกคงที่
วอลนัท

C ++ 17 แทนที่ด้วย " นิพจน์ค่าคงที่ที่แปลงแล้ว " นั่นคืออนุญาตให้เชื่อมโยงนิพจน์ค่าคงที่ได้ดังนั้นwrapper_function<func>()จะใช้งานได้
rustyx

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