В настоящее время я работаю над библиотекой, в которой я объединяю функциональные объекты.
Я создаю шаблон функции, который принимает вызываемый объект (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
трюк для типа возврата функции шаблона?
Спасибо.
Я думаю, что вы можете сделать, это создать промежуточную функцию вывода типа, которая использует 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()
напрямую в любом случае, если нет причин печатать тип функции.
Есть ли способ обойти это, чтобы я мог определить тип ввода / возврата вызываемого объекта без явного упоминания их на сайте вызова?
Пользовательские преобразования не учитываются при выводе аргументов шаблона. Компилятор должен придумать In
а также Out
такой, что тип параметра и тип аргумента должны совпадать (почти) точно, но они никогда не будут в этом случае.
Возможно параметризовать шаблон по типу функции вместо типов ввода / возврата
Да, это то, что обычно делается (посмотрите на стандартные алгоритмы библиотеки, например)