Есть ли способ вывести значение параметра шаблона указателя на функцию?

C ++ позволяет указывать типовые параметры нетипового указателя, включая указатель на функцию, тип. Я недавно спросил вопрос о том, для чего это полезно, и это продолжение один из ответов.

Можно ли вывести значение параметра шаблона указателя на функцию, из аргумента функции, о котором идет речь? Например:

using VoidFunction = void(*)();

template <VoidFunction F>
void templ(VoidFunction);

...

void func();  // a VoidFunction

...

templ<func>(func);  // works, but I have to specify the template parameter explicitly
templ(func);        //  <-- I would like to be able to do this

Есть ли способ заставить этот вывод произойти? Это представляется технически возможным с точки зрения разработчика компилятора, если аргумент функции может быть преобразован в функцию в коде во время компиляции.

Если вас интересует мотивация, см. Комментарии под этот ответ, в частности, возможная оптимизация для реализации std::bind(),

РЕДАКТИРОВАТЬ: Я понимаю, что могу просто удалить аргумент функции и использовать аргумент шаблона, как в templ<func>(), Моей единственной целью добавления в аргумент функции была попытка избежать передачи аргумента шаблона.

Я думаю, что я действительно хочу, это также вывести тип указателя функции, как в:

template <typename Function, Function F>
void templ(/* something */);

а затем сможет позвонить

templ(func);

или же

templ<func>();

и иметь тип и значение, выводимые из одного упоминания указателя функции.

Надеюсь, что это имеет больше смысла сейчас.

6

Решение

Аргументы шаблона для функции выводятся из типов параметров шаблона функции. Аргументы шаблона могут быть выведены из типа, только если этот тип является одной из допустимых форм. Разрешенные формы указаны в [temp.deduct.type]

Аргументы шаблона могут быть выведены в нескольких различных контекстах, но в каждом случае тип, который указан в терминах параметров шаблона (назовите его P) сравнивается с фактическим типом (назовите его A), и делается попытка найти значения аргументов шаблона (тип для параметра типа, значение для нетипового параметра или шаблон для параметра шаблона), который создаст P, после подстановки выведенных значений (назовите это выведенными A), совместим с A,

Аргумент типа шаблона Tшаблонный аргумент TT или шаблон не тип аргумента i можно вывести, если P а также A иметь одну из следующих форм:

T
c-list T
T *
T
Т [целое число-константа]
имя шаблона (где имя шаблона относится к шаблону класса)
тип (*) (Т)
Т (*) ()
Т (*) (Т)
T type :: *
тип T :: *
Т Т :: *
T (тип :: *) ()
тип (T :: *) ()
тип (тип :: *) (T)
тип (T :: *) (T)
T (тип :: *) (T)
T (T :: *) ()
T (T :: *) (T)
тип [я]
template-namelti> (где template-name ссылается на шаблон класса)
TT<T>
TT<я>
TT<>

где (T) представляет списки аргументов, где хотя бы один тип аргумента содержит T, а также () представляет списки аргументов, где ни один параметр не содержит T, Так же, <T> представляет списки аргументов шаблона, где хотя бы один аргумент содержит T, <i> представляет списки аргументов шаблона, где хотя бы один аргумент содержит i а также <> представляет списки аргументов шаблона, где ни один аргумент не содержит T или i,

При рассмотрении только не типовых аргументов шаблона, соответствующие формы, которые содержат i:

тип [я]
template-namelti> (где template-name ссылается на шаблон класса)
TT<я>

Поэтому невозможно вывести значение непосредственно из значения аргумента функции, который является указателем функции. Однако это является можно вывести значение аргумента шаблона нетипичного типа, если параметр функции имеет одну из указанных форм.

Следующий код демонстрирует это, оборачивая нетипичное значение аргумента шаблона в шаблон класса с именем NonType, Параметр f в форме template-name<i>, что делает возможным вывод значения его нетипичного аргумента шаблона.

template<typename T, T value>
struct NonType {};

template<typename T, T value>
void f(NonType<T, value>)
{
}

void g();

struct A
{
void f();
int m;
};

int i;

#define MAKE_NONTYPE(value) NonType<decltype(value), (value)>()

int main()
{
f(MAKE_NONTYPE(0)); // NonType<int, 0>
f(MAKE_NONTYPE(&g)); // NonType<void(*)(), &g>
f(MAKE_NONTYPE(&A::f)); // NonType<void(A::*)(), &A::f>
f(MAKE_NONTYPE(&A::m)); // NonType<int A::*, &A::m>
f(MAKE_NONTYPE(&i)); // NonType<int*, &i>
}

Обратите внимание, что decltype и MAKE_NON_TYPE макрос используется здесь только для удобства, чтобы избежать необходимости выписывать полный список аргументов шаблона NonType

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]