From: Tom Jackson Date: Thu, 29 Jan 2015 18:22:59 +0000 (-0800) Subject: indirect(), for making pointers out of refs X-Git-Tag: v0.23.0~8 X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=d6415c69d589b71dc148564f465d4f101ff0711f;p=folly.git indirect(), for making pointers out of refs Test Plan: Unit tests Reviewed By: ajaymenon@fb.com Subscribers: trunkagent, folly-diffs@ FB internal diff: D1808023 Signature: t1:1808023:1422410709:8db2d73d5b4c0c2eab563643e5fa1557ebfd4730 --- diff --git a/folly/gen/Base-inl.h b/folly/gen/Base-inl.h index faaa92ac..083cf979 100644 --- a/folly/gen/Base-inl.h +++ b/folly/gen/Base-inl.h @@ -1854,6 +1854,58 @@ class Dereference : public Operator { } }; +/** + * Indirect - For producing a sequence of the addresses of the values in the + * input. + * + * This type is usually used through the 'indirect' static value, like: + * + * auto ptrs = from(refs) | indirect; + */ +class Indirect : public Operator { + public: + Indirect() {} + + template ::type*> + class Generator : public GenImpl> { + Source source_; + static_assert(!std::is_rvalue_reference::value, + "Cannot use indirect on an rvalue"); + + public: + explicit Generator(Source source) : source_(std::move(source)) {} + + template + void foreach (Body&& body) const { + source_.foreach([&](Value value) { + return body(&value); + }); + } + + template + bool apply(Handler&& handler) const { + return source_.apply([&](Value value) -> bool { + return handler(&value); + }); + } + + // not actually infinite, since an empty generator will end the cycles. + static constexpr bool infinite = Source::infinite; + }; + + template > + Gen compose(GenImpl&& source) const { + return Gen(std::move(source.self())); + } + + template > + Gen compose(const GenImpl& source) const { + return Gen(source.self()); + } +}; + } //::detail /** @@ -1965,6 +2017,8 @@ static const detail::Cycle cycle; static const detail::Dereference dereference; +static const detail::Indirect indirect; + inline detail::Take take(size_t count) { return detail::Take(count); } diff --git a/folly/gen/Base.h b/folly/gen/Base.h index bbae117a..12d917ed 100644 --- a/folly/gen/Base.h +++ b/folly/gen/Base.h @@ -342,6 +342,8 @@ class Batch; class Dereference; +class Indirect; + /* * Sinks */ diff --git a/folly/gen/test/BaseTest.cpp b/folly/gen/test/BaseTest.cpp index 2ff11c83..2b99f157 100644 --- a/folly/gen/test/BaseTest.cpp +++ b/folly/gen/test/BaseTest.cpp @@ -124,7 +124,7 @@ TEST(Gen, Member) { | sum); EXPECT_EQ(10 * (1 + 10) / 2, from(counters) - | mapped([](const Counter& c) { return &c; }) + | indirect | member(&Counter::count) | sum); EXPECT_EQ(10 * (2 + 11) / 2, @@ -133,7 +133,7 @@ TEST(Gen, Member) { | sum); EXPECT_EQ(10 * (3 + 12) / 2, from(counters) - | mapped([](Counter& c) { return &c; }) + | indirect | member(&Counter::incr) | sum); EXPECT_EQ(10 * (3 + 12) / 2, @@ -1010,6 +1010,11 @@ TEST(Gen, Dereference) { } } +TEST(Gen, Indirect) { + vector vs{1}; + EXPECT_EQ(&vs[0], from(vs) | indirect | first); +} + TEST(Gen, Guard) { using std::runtime_error; EXPECT_THROW(from({"1", "a", "3"})