разрешение аргументов шаблона std :: function

В настоящее время я работаю над библиотекой, в которой я объединяю функциональные объекты.

Я создаю шаблон функции, который принимает вызываемый объект (std :: function на данный момент) и параметризован на типе вывода и ввода функции. Вот упрощенная версия того, что я определяю:

template <typename In, typename Out>
std::vector<Out> process(std::vector<In> vals, std::function< Out(In) > func)
{
// apply func for each value in vals
return result;
}

У меня проблема в использовании. Кажется, что когда я передаю лямбду, компилятор не может правильно определить тип, поэтому жалуется, что функция не существует:

std::vector<string> strings;
// does NOT compile
auto chars = process(strings,
[]( std::string s ) -> char
{
return s[0]; // return first char
}
);

Если я явно обернуть лямбда в std::functionПрограмма компилирует:

std::vector<string> strings;
// DOES compile
auto chars = process(strings,
std::function< char(std::string) >(
[]( std::string s ) -> char
{
return s[0]; // return first char
})
);

Я еще не тестировал передаваемые указатели на функции или функциональные объекты, но кажется, что компилятору будет трудно вывести In а также Out параметры, если я не передаю прямо явное std::function объект.

У меня такой вопрос: есть ли способ обойти это, чтобы я мог определить тип ввода / возврата вызываемого объекта без явного упоминания их на сайте вызова?

Возможно параметризовать шаблон на тип функции вместо типов ввода / возврата? По сути, мне нужно вывести In а также Out Тип для произвольного вызова. Возможно, какой-то auto/decltype трюк для типа возврата функции шаблона?

Спасибо.

8

Решение

Я думаю, что вы можете сделать, это создать промежуточную функцию вывода типа, которая использует decltype чтобы определить аргументы, которые будут переданы фактическому объекту функции:

template <typename Out, typename In>
std::vector<Out> process_intern(std::vector<In> vals, std::function< Out(In) > func)
{
// whatever
}

template <typename In, typename Func>
auto process(std::vector<In> vals, Func func) -> std::vector<decltype(func(vals[0]))>
{
return process_intern<decltype(func(vals[0]))>(vals, func);
}

Конечно, вы можете рассмотреть возможность реализации логики в process() напрямую в любом случае, если нет причин печатать тип функции.

9

Другие решения

Есть ли способ обойти это, чтобы я мог определить тип ввода / возврата вызываемого объекта без явного упоминания их на сайте вызова?

Пользовательские преобразования не учитываются при выводе аргументов шаблона. Компилятор должен придумать In а также Out такой, что тип параметра и тип аргумента должны совпадать (почти) точно, но они никогда не будут в этом случае.

Возможно параметризовать шаблон по типу функции вместо типов ввода / возврата

Да, это то, что обычно делается (посмотрите на стандартные алгоритмы библиотеки, например)

8

По вопросам рекламы [email protected]