Gostaria de passar um ponteiro de função de uma matriz de ponteiros de função como um argumento de modelo. Meu código parece compilar usando o MSVC, apesar do Intellisense reclamar que algo está errado. O gcc e o clang falham ao compilar o código.
Considere o seguinte exemplo:
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 compila o código, mas o Intellisense fornece o seguinte erro:invalid nontype template argument of type "const FunctionPointer"
O gcc falha ao compilar com a seguinte mensagem:
<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
O clang falha ao compilar com a seguinte mensagem:
<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.
Questões:
É wrapper_function<functions[0]>();
válido ou não?
Se não for, há algo que eu possa fazer para passar functions[0]
como argumento de modelo wrapper_function
? Meu objetivo é construir uma nova matriz de ponteiros de função em tempo de compilação, com o conteúdo { wrapper_function<functions[0]>, ..., wrapper_function<functions[std::size(functions) - 1]> }
.
wrapper_function<decltype(functions[0])>()
compila.Respostas:
A expressão
wrapper_function<functions[0]>();
é proibida devido ao seguinte:É proibido usar ponteiros como argumentos de modelo que não sejam do tipo, exceto no formulário
&id
, portanto, basicamente, o seguinte funcionaria:e o seguinte snippet não funcionará quando compilado com a opção C ++ 14:
Quando compilada com a opção C ++ 17, sua abordagem e a acima funcionariam:
Ver ao vivo
fonte
&id
, mas tambémid
é permitido para funções, como você está demonstrando no exemplo, e um valor de ponteiro nulo é explicitamente permitido no formulário de expressão constante.wrapper_function<func>()
que também funcione.