Можно ли передать шаблон функции в качестве аргумента шаблона?
Предположим, что у нас есть шаблонная функция:
template<typename T1, typename T2, typename T3>
T3 such_fun(T1 a, T2 b) {
// do something...
}
и теперь мы хотим использовать его в качестве аргумента в другом шаблоне, например. как это
template<typename T1, template<typename, typename, typename> some_function>
void big_fun(T1 a) {
// some code...
a = some_function<T1, T1, T1>(a, a);
// some code...
}
Возможно ли это?
Я знаю, что могу использовать struct с определенным() оператором. Мне просто интересно узнать о функциях.
EDIT:
Пока я писал этот вопрос, мой друг нашел частичное решение:
template<typename T1, T1 (*some_function)(T1, T1)>
void big_fun(T1 a) {
// some code...
a = some_function(a, a);
// some code...
}
Но все же - мне любопытно, возможно ли это без материализации типа функции перед вызовом. Например, я могу вызвать переданный шаблон с различными типами комбинаций:
template<typename T1, typename T2, template<typename, typename, typename> some_function>
void big_fun(T1 a, T2 b) {
// some code...
a = some_function<T1, T1, T1>(a, a);
a = some_function<T1, T2, T1>(a, b);
b = some_function<T2, T2, T2>(b, b);
b = some_function<T2, T1, T2>(b, a);
// some code...
}
Ответы
Ответ 1
Нет, это невозможно. Из 14.3.3 в N3337:
Аргумент шаблона для шаблона-шаблона шаблона должен быть имя шаблона класса или шаблон псевдонима, выраженный как id-выражение. Когда шаблон-аргумент называет шаблон класса, при сопоставлении шаблона учитываются только шаблоны первичного класса аргумент шаблона с соответствующим параметром; частичный специализации не учитываются, даже если их списки параметров совпадают параметра шаблона шаблона.
В первом параграфе явно упоминаются шаблоны классов. Я думаю, это также не стоит того, чтобы вы могли сделать что-то очень похожее с функциями или std::function
в качестве аргумента.
Ответ 2
Шаблоны в С++ скомпилированы во время компиляции с использованием конкретных типов. Они должны быть известны.
Это говорит о том, что вы можете пойти немного дальше с частичным решением, передав шаблон функции, аргументы которого можно вывести. Обратите внимание, что это ничем не отличается от явной передачи функции с конкретными типами, которые вам просто нужно набрать меньше.
template<typename T>
T square(T a, T b)
{
return a * b;
}
template<typename T, T (*some_function)(T, T)>
T test(T a)
{
return square (a, a);
}
void main()
{
int a = test<int, square>(2);
float b = test<float, square>(2.2f);
}
Ответ 3
Пока template< typename T1, typename T2, typename T3> someTemplate
оценивает некоторый фактический класс без ошибок, вы можете использовать его с таким количеством комбинаций, сколько хотите, из других шаблонов и внутри них.
Вы пытались скомпилировать его? Покажите нам, какую ошибку вы получаете (и конкретную выборку)