Bir işlev işaretçisi dizisinden işlev işaretçisini şablon argümanı olarak iletme


9

Bir şablon işaretçisi olarak işlev işaretçisi bir dizi bir işlev işaretçisi geçmek istiyorum. Intellisense bir şeylerin yanlış olduğundan şikayetçi olsa bile kodum MSVC kullanarak derleniyor. Hem gcc hem de clang kodu derleyememektedir.

Aşağıdaki örneği düşünün:

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 kodu derler, ancak Intellisense aşağıdaki hatayı verir:invalid nontype template argument of type "const FunctionPointer"

gcc aşağıdaki mesajla derlenemez:

<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

clang aşağıdaki mesajla derlenemez:

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

Sorular:

Mi wrapper_function<functions[0]>();geçerli veya olmasın?

Değilse, functions[0]şablon argümanı olarak geçmek için yapabileceğim bir şey var wrapper_functionmı? Amacım, derleme zamanında içerikle birlikte yeni bir işlev işaretçileri dizisi oluşturmak { wrapper_function<functions[0]>, ..., wrapper_function<functions[std::size(functions) - 1]> }.


Hmm ilginç, sorun bir tür yerine bir değer (işaretçi) kullanmak olduğunu düşündüm. Ama wrapper_function<decltype(functions[0])>()derlemiyor bile .
Cory Kramer

6
C ++ 17'de çalışıyor gibi görünüyor ... şimdi standardese farkı bulmak için ...
AndyG

Yanıtlar:


5

wrapper_function<functions[0]>();Aşağıdakiler nedeniyle ifade etmek yasaktır:

14.3.2 Şablon türü olmayan bağımsız değişkenler [temp.arg.nontype]

Tür olmayan, şablon olmayan bir şablon parametresi için şablon bağımsız değişkeni şunlardan biri olacaktır:

[...]

- statik depolama> süresi ve harici veya dahili bağlantısı olan bir nesnenin adresini veya işlev şablonları ve işlev şablonu kimlikleri dahil ancak statik olmayan sınıf üyeleri hariç olmak üzere harici veya dahili bağlantıya sahip bir işlevi belirten sabit bir ifade (5.19) (parantez yoksayılır) & id ifadesi olarak adlandırılır, ancak ad, bir işleve veya diziye başvuruyorsa & öğesinin atlanabileceği ve karşılık gelen template-parametresi başvuru olduğunda atlanacaktır; [...]

İşaretçileri form dışında tür olmayan şablon bağımsız değişkenleri olarak kullanmak yasaktır, &idbu nedenle temelde aşağıdakiler işe yarar :

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
}

ve aşağıdaki snippet, C ++ 14 seçeneğiyle derlendiğinde çalışmaz:

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

C ++ 17 seçeneğiyle derlendiğinde, yaklaşımınız ve yukarıdaki yaklaşım her ikisi de işe yarar:

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

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

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

Bkz canlı


Örnekte gösterdiğiniz ve yalnızca sabit ifade biçiminde boş bir işaretçi değerine açıkça izin verildiği gibi &id, yalnızca form değil , idişlevler için de izin verilir.
Ceviz

C ++ 17, bir " dönüştürülmüş sabit ifade " ile değiştirilir, yani sabit ifadelerin zincirlenmesine izin verir, böylece wrapper_function<func>()de çalışır.
rustyx

Tamam, ben tamamen yazdıktan sonra cevap kontrol edecek ve güncelleyecektir. Tnx
NutCracker
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.