У меня есть функция GetThing
следующим образом:
auto GetThing(size_t index, auto&& l1)
{
return l1;
}
auto GetThing(size_t index, auto&& l1, auto&&... rest)
{
if (index == 0)
return l1;
return GetThing(index - 1, rest...);
}
Я хочу, чтобы она также могла работать с разными лямбдами , имея при этом возможность обрабатывать другие типы (то есть не лямбды, не функции, такие как int
и ...) , например
std::cout << GetThing(1, 2, 3, 4); //works, return 3
std::cout << GetThing(1, [] {return 0; },
[] {return 1; }, [] {return 2; },
[] {return 3; } )(); //nope
Но проблема здесь в том, что лямбды имеют другой тип, поэтому рекурсивная функция будет выведена на несовместимый тип возврата, поэтому мне кажется, что я должен использовать std::function
вот так, но это некрасиво.
std::cout << GetThing(1, std::function{ [] {return 0; } }, std::function{ [] {return 1; } }, std::function{ [] {return 2; } }, std::function{ [] {return 3; } })();//works
Любой способ обойти это, например, если есть перегруженный operator()
, тогда он автоматически применяет тип быть std::function
?
РЕДАКТИРОВАТЬ: Я знаю, что лямбда-выражения без захвата могут быть преобразованы в указатель функции, но как это сделать без std::decay
в шаблоне? Поскольку я все еще хочу обрабатывать другие типы как ссылки
EDIT2: я получаю несколько ответов, использующих std::variant
, и думаю о том, что, помимо лямбда, типы параметров должны быть такими же, например. std::variant<int, int, int>
. Возможно, можно добавить перегрузку к GetThing
, так что, когда std::variant
содержит те же типы, он возвращает объект этого типа, в противном случае (что является случаем получения лямбда-выражений) возвращает std::function