#cpp #шаблоны_с++ #cpp14
Как правильно написать функцию test, чтобы ей в качестве аргумента (либо шаблонного параметра - не важно) можно было передать любую из функций f и g, с возможностью их вызова с разным типом аргумента (в примере int, char и long). http://ideone.com/1aZ8Zu #includeusing namespace std; template auto f(T x) -> decltype(x*x) { return x * x; } template T g(T x) { return x * x; } template 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 class F> void test(F f) ^ prog.cpp:15:49: error: missing template arguments before 'f' template 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); ^
Ответы
Ответ 1
Могу порекомендовать в определенном смысле обходной, но в определенном - и прямой путь. В C++14 (а у вас четко указан этот тэг) лямбды тоже могут быть шаблонами. auto f = [](auto x){ cout << x << endl; return x*x; }; templatevoid 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 T g_(T x) { return x * x * x; } auto g = [](auto x){ cout << typeid(x).name() << endl; return g_(x); }; template 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 Ответ 2
Немного теории. Для того, чтобы можно было вызывать f(42) и f(42L) одновременно - переменная f должна быть типа, у которого определен шаблонный оператор (): struct F { templatevoid operator () (T value); }; void test(F f); // работает Если же переставить шаблон в другое место - то вы не сможете инстанцировать F: template struct F { void operator () (T value); }; void test(F f); // ошибка компиляции: F - это шаблон типа, а не тип Проблема с функциями - в том, что ссылка на шаблонную функцию больше похожа по своим свойствам на вторую форму записи, чем на первую. Как уже написал @Harry - для неявного создания структуры первого типа можно использовать лябмды: auto g = [](auto x){ return x*x; }; template test(F f); // сюда можно передать переменную g Ответ 3
Это невозможно, в том виде, что Вы хотите. Вы имеете две шаблонных функции test и f, которые встречаются в одном выражении, и в которых тип аргумента должен быть выведен из переданных аргументов. Что может вывести из этой test(f) строчки компилятор? Ничего, т.к. нет никакой уточняющей информации, конкретизирующей, что за версию нужно инстанциировать.
Комментариев нет:
Отправить комментарий