Me gustaría pasar un puntero de función de una matriz de punteros de función como argumento de plantilla. Mi código parece compilarse usando MSVC aunque Intellisense se queja de que algo está mal. Tanto gcc como clang no pueden compilar el código.
Considere el siguiente ejemplo:
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 el código pero Intellisense da el siguiente error:invalid nontype template argument of type "const FunctionPointer"
gcc falla al compilar con el siguiente mensaje:
<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 no se compila con el siguiente mensaje:
<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.
Preguntas:
¿Es wrapper_function<functions[0]>();
válido o no?
Si no es así, ¿hay algo que pueda hacer para pasar functions[0]
como argumento de plantilla wrapper_function
? Mi objetivo es construir una nueva matriz de punteros de función en tiempo de compilación, con el contenido { wrapper_function<functions[0]>, ..., wrapper_function<functions[std::size(functions) - 1]> }
.
wrapper_function<decltype(functions[0])>()
no compila.Respuestas:
La expresión
wrapper_function<functions[0]>();
está prohibida por lo siguiente:Está prohibido usar punteros como argumentos de plantilla que no sean de tipo distinto del formulario
&id
, por lo que, básicamente, lo siguiente funcionaría:y el siguiente fragmento no funcionará cuando se compila con la opción C ++ 14:
Cuando se compila con la opción C ++ 17, su enfoque y el anterior funcionarían:
Ver en vivo
fuente
&id
, sino que tambiénid
está permitida para funciones, como está demostrando en el ejemplo y un valor de puntero nulo está explícitamente permitido en forma de expresión constante.wrapper_function<func>()
lo que también funcionará.