टेम्प्लेट तर्क के रूप में फ़ंक्शन पॉइंटर की एक सरणी से एक फ़ंक्शन पॉइंटर पास करना


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"

जीसीसी निम्न संदेश के साथ संकलित करने के लिए विफल रहता है:

<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])>()कि संकलन नहीं है।
कोरी क्रेमर

6
C ++ 17 में काम करने लगता है ... अब मानक में अंतर खोजने के लिए ...
एंडीजी

जवाबों:


5

wrapper_function<functions[0]>();निम्नलिखित के कारण अभिव्यक्ति निषिद्ध है:

14.3.2 टेम्पलेट गैर-प्रकार के तर्क [temp.arg.nontype]

गैर-प्रकार, गैर-टेम्पलेट टेम्पलेट-पैरामीटर के लिए एक टेम्पलेट-तर्क निम्न में से एक होगा:

[...]

- एक स्थिर अभिव्यक्ति (5.19) जो स्थिर भंडारण> अवधि और बाहरी या आंतरिक लिंकेज या फ़ंक्शन या बाहरी या आंतरिक लिंकेज के साथ एक फ़ंक्शन के पते को डिज़ाइन करता है, जिसमें फ़ंक्शन टेम्पलेट और फ़ंक्शन टेम्पलेट-आईडी शामिल हैं, लेकिन गैर-स्थिर वर्ग के सदस्यों को छोड़कर, व्यक्त किया गया (कोष्ठक की अनदेखी) के रूप में & आईडी-एक्सप्रेशन, सिवाय इसके कि & छोड़ा जा सकता है यदि नाम किसी फ़ंक्शन या सरणी को संदर्भित करता है और छोड़ा जा सकता है यदि संबंधित टेम्पलेट-पैरामीटर एक संदर्भ है; [...]

यह इंगित करने के लिए निषिद्ध है कि गैर-प्रकार टेम्पलेट तर्क के रूप में अन्य के रूप में उपयोग किया जाता है &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कार्यों के लिए भी अनुमति दी जाती है, जैसा कि आप उदाहरण में प्रदर्शित कर रहे हैं और एक अशक्त सूचक मान को स्पष्ट रूप से निरंतर अभिव्यक्ति रूप में अनुमति दी जाती है।
अखरोट

सी ++ 17 का अर्थ है कि " परिवर्तित स्थिर अभिव्यक्ति " के साथ, अर्थात यह निरंतर अभिव्यक्ति को चेन करने की अनुमति देता है इसलिए wrapper_function<func>()यह भी काम करेगा।
रस्टीक्स

ठीक है, मैं पूरी तरह से लिखने के बाद उत्तर की जांच और अद्यतन करूंगा। Tnx
नटक्रैकर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.