Требуется преобразование лямбда-функции в boost::function<void(ArgT)>
, где ArgT
должно быть выведено. Как правило, вы не можете иметь вывод и преобразование типов в одном и том же аргументе функции: при выводе параметра шаблона * преобразования не выполняются .
Причина этого заключается в следующем. Здесь используются три типа: (1) параметр шаблона, (2) тип параметра функции, (3) передаваемый тип объекта. Два типа (1 и 2) могут быть выведены друг от друга, но оба неизвестны. Если компилятор может предположить, что 2 и 3 относятся к одному и тому же типу, проблема решена, но если все, что знает компилятор, это то, что 3 можно преобразовать в 2, может быть любое количество возможных решений, и компилятор не должен решать проблема. На практике мы знаем, что в данном конкретном случае есть только одно возможное решение, но стандарт не проводит различия между случаями.
Приведенное выше правило применяется во всех выводимых контекстах, , даже если параметр шаблона может быть выведен из другого параметра функции . Решение здесь состоит в том, чтобы сделать соответствующий параметр функции невыводимым контекстом , то есть контекстом, в котором компилятор никогда не будет пытаться вывести параметр шаблона из параметра функции. Это можно сделать следующим образом:
template <class T> struct identity { typename T type; };
template <class ArgT>
void foo(ArgT arg, typename identity<::boost::function<void(ArgT)>>::type func)
{
func(arg);
}