Проблема в том, что если в шаблоне один из его параметров функции не является ссылочным типом до начала вывода, этот параметр никогда не будет выведен в ссылочный тип. Таким образом, в дедукции в левой части T
дает int
, а в дедукции в правой части T
дает int&
. Это ошибочное совпадение, и компилятор жалуется.
Лучше всего сделать параметр функции того же типа, что и тип параметра указателя функции:
template<typename T> struct identity { typedef T type; };
template<typename T>
void f(typename identity<T>::type t, void (*func)(T)) {}
Используя identity<T>::type
, вы отключаете удержание в левой части. Как только T
был определен с правой стороны, T
подставляется в левую часть и дает окончательный тип параметра.
Один парень предложил использовать правую сторону в качестве параметра шаблона - это хорошо, так как тогда он может принимать объекты функций с operator()
перегруженными. Но тогда вы сталкиваетесь с проблемой необходимости знать, нужна ли ему ссылка или нет. Чтобы решить эту проблему, у boost
есть reference_wrapper
(кстати, у boost
также есть шаблон identity
выше).
template<typename T, typename F>
void f(T t, F func) {}
Теперь, если вы хотите передать ссылку, а не копию, вы можете сделать это следующим образом
int i;
f(boost::ref(i), some_function);
ref
возвращает объект reference_wrapper, который неявно конвертируется в T&
. Поэтому, если вы вызываете func(t)
, t
автоматически преобразуется в целевую ссылку. Если вы не хотите передавать ссылку, просто передайте i
напрямую.
person
Johannes Schaub - litb
schedule
29.03.2010