Make map work without specifying the type
This commit updates `ranget.map` so that the type is inferred from the return type of the function passed. This makes the usage of `map` less verbose and makes it more inline with other `ranget` operations like `filter`.
This commit is contained in:
parent
f7014671b0
commit
7ba5f29533
|
@ -441,7 +441,7 @@ void show_compact_goto_trace(
|
|||
|
||||
{
|
||||
auto arg_strings = make_range(step.function_arguments)
|
||||
.map<std::string>([&ns, &step](const exprt &arg) {
|
||||
.map([&ns, &step](const exprt &arg) {
|
||||
return from_expr(ns, step.function, arg);
|
||||
});
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ Author: Romain Brenguier, romain.brenguier@diffblue.com
|
|||
#define CPROVER_UTIL_RANGE_H
|
||||
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
|
||||
#include <util/invariant.h>
|
||||
#include <util/make_unique.h>
|
||||
|
@ -300,13 +301,17 @@ public:
|
|||
return ranget<filter_iteratort<iteratort>>(filter_begin, filter_end);
|
||||
}
|
||||
|
||||
/// Template argument type `outputt` has to be specified when \p f is given as
|
||||
/// a lambda.
|
||||
template <typename outputt>
|
||||
ranget<map_iteratort<iteratort, outputt>>
|
||||
map(std::function<outputt(const value_typet &)> f)
|
||||
/// The type of elements contained in the resulting range is deduced from the
|
||||
/// return type of \p `f`.
|
||||
template <typename functiont>
|
||||
auto map(functiont &&f) -> ranget<map_iteratort<
|
||||
iteratort,
|
||||
typename std::result_of<functiont(value_typet)>::type>>
|
||||
{
|
||||
auto shared_f = std::make_shared<decltype(f)>(std::move(f));
|
||||
using outputt = typename std::result_of<functiont(value_typet)>::type;
|
||||
auto shared_f = std::make_shared<
|
||||
std::function<outputt(const typename iteratort::value_type &)>>(
|
||||
std::forward<functiont>(f));
|
||||
auto map_begin =
|
||||
map_iteratort<iteratort, outputt>(begin(), end(), shared_f);
|
||||
auto map_end = map_iteratort<iteratort, outputt>(end(), end(), shared_f);
|
||||
|
|
|
@ -29,8 +29,8 @@ SCENARIO("range tests", "[core][util][range]")
|
|||
}
|
||||
THEN("Use map to compute individual lengths")
|
||||
{
|
||||
auto length_range = make_range(list).map<std::size_t>(
|
||||
[](const std::string &s) { return s.length(); });
|
||||
auto length_range =
|
||||
make_range(list).map([](const std::string &s) { return s.length(); });
|
||||
auto it = length_range.begin();
|
||||
REQUIRE(*it == 3);
|
||||
++it;
|
||||
|
@ -54,7 +54,7 @@ SCENARIO("range tests", "[core][util][range]")
|
|||
auto range =
|
||||
make_range(list)
|
||||
.filter([&](const std::string &s) -> bool { return s[0] == 'a'; })
|
||||
.map<std::size_t>([&](const std::string &s) { return s.length(); });
|
||||
.map([&](const std::string &s) { return s.length(); });
|
||||
// Note that everything is performed on the fly, so none of the filter
|
||||
// and map functions have been computed yet, and no intermediary container
|
||||
// is created.
|
||||
|
|
Loading…
Reference in New Issue