Как правильно написать функцию test
, чтобы ей в качестве аргумента (либо шаблонного параметра - не важно) можно было передать любую из функций f
и g
, с возможностью их вызова с разным типом аргумента (в примере int, char и long).
http://ideone.com/1aZ8Zu
#include <iostream>
using namespace std;
template <typename T> auto f(T x) -> decltype(x*x)
{
return x * x;
}
template <typename T> T g(T x)
{
return x * x;
}
template <template <class> class F> void test(F f)
{
auto a = f(32);
auto b = f(' ');
auto c = f(2000000000L);
cout << a << ' ' << b << ' ' << c << endl;
}
int main()
{
test(f);
test(g);
return 0;
}
Этот код не компилируется с сообщениями:
prog.cpp:15:47: error: variable or field 'test' declared void
template <template <class> class F> void test(F f)
^
prog.cpp:15:49: error: missing template arguments before 'f'
template <template <class> class F> void test(F f)
^
prog.cpp: In function 'int main()':
prog.cpp:26:8: error: 'test' was not declared in this scope
test(f);
^
Могу порекомендовать в определенном смысле обходной, но в определенном - и прямой путь. В C++14 (а у вас четко указан этот тэг) лямбды тоже могут быть шаблонами.
auto f = [](auto x){ cout << x << endl; return x*x; };
template<typename F> void test(F f)
{
auto a = f(32);
auto b = f(' ');
auto c = f(2000000000ull);
cout << a << ' ' << b << ' ' << c << endl;
}
int main()
{
test(f);
return 0;
}
Вызывается f
именно как шаблон (разная для разных аргументов).
Да, это не есть абсолютно строгий и точный ответ на заданный вопрос, но - шаблон в шаблоне вызван :)
Можно использовать лямбду и как уровень косвенности:
template <typename T> T g_(T x)
{
return x * x * x;
}
auto g = [](auto x){ cout << typeid(x).name() << endl; return g_(x); };
template<typename F> void test(F f)
{
auto a = f(32);
auto b = f(' ');
auto c = f(2000000000ull);
cout << a << ' ' << b << ' ' << c << endl;
}
int main()
{
test(g);
return 0;
}
Пример на ideone: http://ideone.com/kfUWtx
Немного теории.
Для того, чтобы можно было вызывать f(42)
и f(42L)
одновременно - переменная f
должна быть типа, у которого определен шаблонный оператор ()
:
struct F {
template <typename T> void operator () (T value);
};
void test(F f); // работает
Если же переставить шаблон в другое место - то вы не сможете инстанцировать F
:
template <typename T> struct F {
void operator () (T value);
};
void test(F f); // ошибка компиляции: F - это шаблон типа, а не тип
Проблема с функциями - в том, что ссылка на шаблонную функцию больше похожа по своим свойствам на вторую форму записи, чем на первую.
Как уже написал @Harry - для неявного создания структуры первого типа можно использовать лябмды:
auto g = [](auto x){ return x*x; };
template<typename F> test(F f); // сюда можно передать переменную g
Это невозможно, в том виде, что Вы хотите. Вы имеете две шаблонных функции test
и f
, которые встречаются в одном выражении, и в которых тип аргумента должен быть выведен из переданных аргументов. Что может вывести из этой test(f)
строчки компилятор? Ничего, т.к. нет никакой уточняющей информации, конкретизирующей, что за версию нужно инстанциировать.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Есть коммерческое ПО, при каждом запуске оно подключается к файлу базы данных, файл именуется как uchetatiidb
Мне необходимо каждый час выполнять какие то действияСоздаю что то типа таймера с помощью std::chrono::steady_clock, в while проверяю или пришло время выполнять...
Подскажите где можно найти готовые решения(С исходным кодом) с модерн дизайном интерфейса, как это делают в Steam/Origin