Я хотел бы передать указатель на функцию из массива указателей на функцию в качестве аргумента шаблона. Кажется, мой код компилируется с использованием 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
clang не может скомпилировать следующее сообщение:
<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])>()
не компилируется.Ответы:
Выражение
wrapper_function<functions[0]>();
запрещено из-за следующего:Запрещается использовать указатели в качестве аргументов шаблонного типа, отличного от формы,
&id
поэтому, в основном, будет работать следующее:и следующий фрагмент не будет работать при компиляции с опцией C ++ 14:
При компиляции с опцией C ++ 17 ваш подход и предыдущий будут работать:
Смотреть в прямом эфире
источник
&id
, но иid
функция, а значение нулевого указателя явно разрешено в форме константного выражения.wrapper_function<func>()
также будет работать.