Я хотел бы сохранить функции в упорядоченной коллекции, а затем применить их все к определенной коллекции, что приведет к получению сильно измененных значений, хранящихся в другой коллекции. Моя первоначальная попытка заключалась в создании std::tuple
указанных функций и попытке получить тип результата (std::invoke_result
) для применения их всех к определенному типу:
int main() {
auto multiply = [](const auto arg){ return arg * arg; };
auto change = [](const auto arg){ return std::vector{arg}; };
auto to_string = [](const auto arg){ return arg.size() + " size"; };
auto functions = std::make_tuple(multiply, change, to_string);
std::vector<int> source{1, 2, 3, 4};
using f_type = decltype(functions);
using last_type =
std::tuple_element_t<std::tuple_size_v<f_type> - 1, f_type>;
using result_type =
std::invoke_result_t<last_type, /* size - 2 ret type and so on */>;
/*
* result_type is the type of applying *multiply* to int (type of *source*),
* then applying *change* to the result of *multiply* and then applying
* *to_string* to the result of *change*. Should be std::string.
*/
std::vector<result_type> results{};
}
Проблема в том, что для второго template
параметра std::invoke_result_t
требуется тип, который будет передан оператору вызова объекта типа last_type
. Для этого нужно вычесть единицу перед типом возврата последнего элемента и т. Д. (Может быть много функций).
В конечном итоге я пытаюсь реализовать потоковую библиотеку Java (этот пример будет эквивалентен объединению 3 map
функций). Я также буду держать дополнительные enum
s, которые будут указывать, является ли следующий элемент map
, filter
или какой-либо другой поддерживаемой функцией, так что не будет никакой путаницы относительно того, что должна делать функция - сейчас проблема в том, чтобы начать с такой логикой.
Есть ли способ получить возвращаемый тип, соединяющий произвольное число функций, когда тип передается самому первому из известных ему?
Или, может быть, мой дизайн настолько несовершенен, что мне лучше начать заново, следуя совершенно другой логике?
Отказ от ответственности - я хорошо знаю о предстоящем в C++20
(надеюсь) rangesV3
. Я пытаюсь имитировать их поведение (с некоторыми незначительными изменениями). Мне также известно о boost::adapters
- их использование меня не устраивает, плюс я бы хотел попробовать реализовать нечто подобное.