Commit 8d246c45 authored by Tudor Bosman's avatar Tudor Bosman Committed by Jordan DeLong

movify generators (but mostly operators)

Summary: Make things work with non-copyable generators.

Test Plan: folly/experimental/test

Reviewed By: tjackson@fb.com

FB internal diff: D628520
parent 6aa05bb9
...@@ -93,21 +93,48 @@ class Operator : public FBounded<Self> { ...@@ -93,21 +93,48 @@ class Operator : public FBounded<Self> {
class ResultGen = void> class ResultGen = void>
ResultGen compose(const GenImpl<Value, Source>& source) const; ResultGen compose(const GenImpl<Value, Source>& source) const;
/**
* operator|() - For composing two operators without binding it to a
* particular generator.
*/
template<class Next,
class Composed = detail::Composed<Self, Next>>
Composed operator|(const Operator<Next>& op) const {
return Composed(this->self(), op.self());
}
protected: protected:
Operator() = default; Operator() = default;
Operator(const Operator&) = default; Operator(const Operator&) = default;
Operator(Operator&&) = default; Operator(Operator&&) = default;
}; };
/**
* operator|() - For composing two operators without binding it to a
* particular generator.
*/
template<class Left,
class Right,
class Composed = detail::Composed<Left, Right>>
Composed operator|(const Operator<Left>& left,
const Operator<Right>& right) {
return Composed(left.self(), right.self());
}
template<class Left,
class Right,
class Composed = detail::Composed<Left, Right>>
Composed operator|(const Operator<Left>& left,
Operator<Right>&& right) {
return Composed(left.self(), std::move(right.self()));
}
template<class Left,
class Right,
class Composed = detail::Composed<Left, Right>>
Composed operator|(Operator<Left>&& left,
const Operator<Right>& right) {
return Composed(std::move(left.self()), right.self());
}
template<class Left,
class Right,
class Composed = detail::Composed<Left, Right>>
Composed operator|(Operator<Left>&& left,
Operator<Right>&& right) {
return Composed(std::move(left.self()), std::move(right.self()));
}
/** /**
* GenImpl - Core abstraction of a generator, an object which produces values by * GenImpl - Core abstraction of a generator, an object which produces values by
* passing them to a given handler lambda. All generator implementations must * passing them to a given handler lambda. All generator implementations must
...@@ -145,18 +172,60 @@ class GenImpl : public FBounded<Self> { ...@@ -145,18 +172,60 @@ class GenImpl : public FBounded<Self> {
return true; return true;
}); });
} }
template<class Next,
class Chain = detail::Chain<Value, Self, Next>,
class ValueNext>
Chain operator+(const GenImpl<ValueNext, Next>& next) const {
static_assert(
std::is_same<Value, ValueNext>::value,
"Generators may ony be combined if Values are the exact same type.");
return Chain(*this, next);
}
}; };
template<class LeftValue,
class Left,
class RightValue,
class Right,
class Chain = detail::Chain<LeftValue, Left, Right>>
Chain operator+(const GenImpl<LeftValue, Left>& left,
const GenImpl<RightValue, Right>& right) {
static_assert(
std::is_same<LeftValue, RightValue>::value,
"Generators may ony be combined if Values are the exact same type.");
return Chain(left.self(), right.self());
}
template<class LeftValue,
class Left,
class RightValue,
class Right,
class Chain = detail::Chain<LeftValue, Left, Right>>
Chain operator+(const GenImpl<LeftValue, Left>& left,
GenImpl<RightValue, Right>&& right) {
static_assert(
std::is_same<LeftValue, RightValue>::value,
"Generators may ony be combined if Values are the exact same type.");
return Chain(left.self(), std::move(right.self()));
}
template<class LeftValue,
class Left,
class RightValue,
class Right,
class Chain = detail::Chain<LeftValue, Left, Right>>
Chain operator+(GenImpl<LeftValue, Left>&& left,
const GenImpl<RightValue, Right>& right) {
static_assert(
std::is_same<LeftValue, RightValue>::value,
"Generators may ony be combined if Values are the exact same type.");
return Chain(std::move(left.self()), right.self());
}
template<class LeftValue,
class Left,
class RightValue,
class Right,
class Chain = detail::Chain<LeftValue, Left, Right>>
Chain operator+(GenImpl<LeftValue, Left>&& left,
GenImpl<RightValue, Right>&& right) {
static_assert(
std::is_same<LeftValue, RightValue>::value,
"Generators may ony be combined if Values are the exact same type.");
return Chain(std::move(left.self()), std::move(right.self()));
}
/** /**
* operator|() which enables foreach-like usage: * operator|() which enables foreach-like usage:
* gen | [](Value v) -> void {...}; * gen | [](Value v) -> void {...};
...@@ -193,7 +262,15 @@ template<class Value, ...@@ -193,7 +262,15 @@ template<class Value,
class Op> class Op>
auto operator|(const GenImpl<Value, Gen>& gen, const Operator<Op>& op) -> auto operator|(const GenImpl<Value, Gen>& gen, const Operator<Op>& op) ->
decltype(op.self().compose(gen)) { decltype(op.self().compose(gen)) {
return op.self().compose(gen); return op.self().compose(gen.self());
}
template<class Value,
class Gen,
class Op>
auto operator|(GenImpl<Value, Gen>&& gen, const Operator<Op>& op) ->
decltype(op.self().compose(std::move(gen.self()))) {
return op.self().compose(std::move(gen.self()));
} }
namespace detail { namespace detail {
...@@ -377,10 +454,9 @@ class Chain : public GenImpl<Value, ...@@ -377,10 +454,9 @@ class Chain : public GenImpl<Value,
const First first_; const First first_;
const Second second_; const Second second_;
public: public:
explicit Chain(const GenImpl<Value, First>& first, explicit Chain(First first, Second second)
const GenImpl<Value, Second>& second) : first_(std::move(first))
: first_(first.self()) , second_(std::move(second)) {}
, second_(second.self()) {}
template<class Handler> template<class Handler>
bool apply(Handler&& handler) const { bool apply(Handler&& handler) const {
...@@ -403,8 +479,8 @@ template<class Value, class Source> ...@@ -403,8 +479,8 @@ template<class Value, class Source>
class Yield : public GenImpl<Value, Yield<Value, Source>> { class Yield : public GenImpl<Value, Yield<Value, Source>> {
const Source source_; const Source source_;
public: public:
explicit Yield(const Source& source) explicit Yield(Source source)
: source_(source) { : source_(std::move(source)) {
} }
template<class Handler> template<class Handler>
...@@ -460,8 +536,8 @@ class Map : public Operator<Map<Predicate>> { ...@@ -460,8 +536,8 @@ class Map : public Operator<Map<Predicate>> {
const Source source_; const Source source_;
const Predicate pred_; const Predicate pred_;
public: public:
explicit Generator(const Source& source, const Predicate& pred) explicit Generator(Source source, const Predicate& pred)
: source_(source), pred_(pred) {} : source_(std::move(source)), pred_(pred) {}
template<class Body> template<class Body>
void foreach(Body&& body) const { void foreach(Body&& body) const {
...@@ -478,6 +554,13 @@ class Map : public Operator<Map<Predicate>> { ...@@ -478,6 +554,13 @@ class Map : public Operator<Map<Predicate>> {
} }
}; };
template<class Source,
class Value,
class Gen = Generator<Value, Source>>
Gen compose(GenImpl<Value, Source>&& source) const {
return Gen(std::move(source.self()), predicate_);
}
template<class Source, template<class Source,
class Value, class Value,
class Gen = Generator<Value, Source>> class Gen = Generator<Value, Source>>
...@@ -511,8 +594,8 @@ class Filter : public Operator<Filter<Predicate>> { ...@@ -511,8 +594,8 @@ class Filter : public Operator<Filter<Predicate>> {
const Source source_; const Source source_;
const Predicate pred_; const Predicate pred_;
public: public:
explicit Generator(const Source& source, const Predicate& pred) explicit Generator(Source source, const Predicate& pred)
: source_(source), pred_(pred) {} : source_(std::move(source)), pred_(pred) {}
template<class Body> template<class Body>
void foreach(Body&& body) const { void foreach(Body&& body) const {
...@@ -534,6 +617,13 @@ class Filter : public Operator<Filter<Predicate>> { ...@@ -534,6 +617,13 @@ class Filter : public Operator<Filter<Predicate>> {
} }
}; };
template<class Source,
class Value,
class Gen = Generator<Value, Source>>
Gen compose(GenImpl<Value, Source>&& source) const {
return Gen(std::move(source.self()), predicate_);
}
template<class Source, template<class Source,
class Value, class Value,
class Gen = Generator<Value, Source>> class Gen = Generator<Value, Source>>
...@@ -567,8 +657,8 @@ class Until : public Operator<Until<Predicate>> { ...@@ -567,8 +657,8 @@ class Until : public Operator<Until<Predicate>> {
const Source source_; const Source source_;
const Predicate pred_; const Predicate pred_;
public: public:
explicit Generator(const Source& source, const Predicate& pred) explicit Generator(Source source, const Predicate& pred)
: source_(source), pred_(pred) {} : source_(std::move(source)), pred_(pred) {}
template<class Handler> template<class Handler>
bool apply(Handler&& handler) const { bool apply(Handler&& handler) const {
...@@ -579,6 +669,13 @@ class Until : public Operator<Until<Predicate>> { ...@@ -579,6 +669,13 @@ class Until : public Operator<Until<Predicate>> {
} }
}; };
template<class Source,
class Value,
class Gen = Generator<Value, Source>>
Gen compose(GenImpl<Value, Source>&& source) const {
return Gen(std::move(source.self()), predicate_);
}
template<class Source, template<class Source,
class Value, class Value,
class Gen = Generator<Value, Source>> class Gen = Generator<Value, Source>>
...@@ -609,8 +706,8 @@ public: ...@@ -609,8 +706,8 @@ public:
const Source source_; const Source source_;
const size_t count_; const size_t count_;
public: public:
explicit Generator(const Source& source, size_t count) explicit Generator(Source source, size_t count)
: source_(source) , count_(count) {} : source_(std::move(source)) , count_(count) {}
template<class Handler> template<class Handler>
bool apply(Handler&& handler) const { bool apply(Handler&& handler) const {
...@@ -625,6 +722,13 @@ public: ...@@ -625,6 +722,13 @@ public:
} }
}; };
template<class Source,
class Value,
class Gen = Generator<Value, Source>>
Gen compose(GenImpl<Value, Source>&& source) const {
return Gen(std::move(source.self()), count_);
}
template<class Source, template<class Source,
class Value, class Value,
class Gen = Generator<Value, Source>> class Gen = Generator<Value, Source>>
...@@ -655,8 +759,8 @@ public: ...@@ -655,8 +759,8 @@ public:
const Source source_; const Source source_;
const size_t count_; const size_t count_;
public: public:
explicit Generator(const Source& source, size_t count) explicit Generator(Source source, size_t count)
: source_(source) , count_(count) {} : source_(std::move(source)) , count_(count) {}
template<class Body> template<class Body>
void foreach(Body&& body) const { void foreach(Body&& body) const {
...@@ -690,6 +794,13 @@ public: ...@@ -690,6 +794,13 @@ public:
} }
}; };
template<class Source,
class Value,
class Gen = Generator<Value, Source>>
Gen compose(GenImpl<Value, Source>&& source) const {
return Gen(std::move(source.self()), count_);
}
template<class Source, template<class Source,
class Value, class Value,
class Gen = Generator<Value, Source>> class Gen = Generator<Value, Source>>
...@@ -742,10 +853,12 @@ class Order : public Operator<Order<Selector, Comparer>> { ...@@ -742,10 +853,12 @@ class Order : public Operator<Order<Selector, Comparer>> {
return std::move(vals); return std::move(vals);
} }
public: public:
Generator(const Source& source, Generator(Source source,
const Selector& selector, const Selector& selector,
const Comparer& comparer) const Comparer& comparer)
: source_(source) , selector_(selector) , comparer_(comparer) {} : source_(std::move(source)),
selector_(selector),
comparer_(comparer) {}
VectorType operator|(const Collect<VectorType>&) const { VectorType operator|(const Collect<VectorType>&) const {
return asVector(); return asVector();
...@@ -781,6 +894,13 @@ class Order : public Operator<Order<Selector, Comparer>> { ...@@ -781,6 +894,13 @@ class Order : public Operator<Order<Selector, Comparer>> {
} }
}; };
template<class Source,
class Value,
class Gen = Generator<Value, Source>>
Gen compose(GenImpl<Value, Source>&& source) const {
return Gen(std::move(source.self()), selector_, comparer_);
}
template<class Source, template<class Source,
class Value, class Value,
class Gen = Generator<Value, Source>> class Gen = Generator<Value, Source>>
...@@ -807,9 +927,9 @@ class Composed : public Operator<Composed<First, Second>> { ...@@ -807,9 +927,9 @@ class Composed : public Operator<Composed<First, Second>> {
const Second second_; const Second second_;
public: public:
Composed() {} Composed() {}
Composed(const First& first, const Second& second) Composed(First first, Second second)
: first_(first) : first_(std::move(first))
, second_(second) {} , second_(std::move(second)) {}
template<class Source, template<class Source,
class Value, class Value,
...@@ -820,6 +940,16 @@ class Composed : public Operator<Composed<First, Second>> { ...@@ -820,6 +940,16 @@ class Composed : public Operator<Composed<First, Second>> {
SecondRet compose(const GenImpl<Value, Source>& source) const { SecondRet compose(const GenImpl<Value, Source>& source) const {
return second_.compose(first_.compose(source.self())); return second_.compose(first_.compose(source.self()));
} }
template<class Source,
class Value,
class FirstRet = decltype(std::declval<First>()
.compose(std::declval<Source>())),
class SecondRet = decltype(std::declval<Second>()
.compose(std::declval<FirstRet>()))>
SecondRet compose(GenImpl<Value, Source>&& source) const {
return second_.compose(first_.compose(std::move(source.self())));
}
}; };
/* /*
...@@ -1143,8 +1273,8 @@ public: ...@@ -1143,8 +1273,8 @@ public:
public GenImpl<InnerValue, Generator<Inner, Source, InnerValue>> { public GenImpl<InnerValue, Generator<Inner, Source, InnerValue>> {
const Source source_; const Source source_;
public: public:
explicit Generator(const Source& source) explicit Generator(Source source)
: source_(source) {} : source_(std::move(source)) {}
template<class Handler> template<class Handler>
bool apply(Handler&& handler) const { bool apply(Handler&& handler) const {
...@@ -1161,6 +1291,13 @@ public: ...@@ -1161,6 +1291,13 @@ public:
} }
}; };
template<class Value,
class Source,
class Gen = Generator<Value, Source>>
Gen compose(GenImpl<Value, Source>&& source) const {
return Gen(std::move(source.self()));
}
template<class Value, template<class Value,
class Source, class Source,
class Gen = Generator<Value, Source>> class Gen = Generator<Value, Source>>
...@@ -1190,8 +1327,8 @@ public: ...@@ -1190,8 +1327,8 @@ public:
: public GenImpl<InnerValue, Generator<Source, Range, InnerValue>> { : public GenImpl<InnerValue, Generator<Source, Range, InnerValue>> {
const Source source_; const Source source_;
public: public:
Generator(const Source& source) explicit Generator(Source source)
: source_(source) {} : source_(std::move(source)) {}
template<class Body> template<class Body>
void foreach(Body&& body) const { void foreach(Body&& body) const {
...@@ -1215,6 +1352,13 @@ public: ...@@ -1215,6 +1352,13 @@ public:
} }
}; };
template<class Value,
class Source,
class Gen = Generator<Source, Value>>
Gen compose(GenImpl<Value, Source>&& source) const {
return Gen(std::move(source.self()));
}
template<class Value, template<class Value,
class Source, class Source,
class Gen = Generator<Source, Value>> class Gen = Generator<Source, Value>>
...@@ -1251,8 +1395,8 @@ class VirtualGen : public GenImpl<Value, VirtualGen<Value>> { ...@@ -1251,8 +1395,8 @@ class VirtualGen : public GenImpl<Value, VirtualGen<Value>> {
class WrapperImpl : public WrapperBase { class WrapperImpl : public WrapperBase {
const Wrapped wrapped_; const Wrapped wrapped_;
public: public:
WrapperImpl(const Wrapped& wrapped) explicit WrapperImpl(Wrapped wrapped)
: wrapped_(wrapped) { : wrapped_(std::move(wrapped)) {
} }
virtual bool apply(const std::function<bool(Value)>& handler) const { virtual bool apply(const std::function<bool(Value)>& handler) const {
...@@ -1271,10 +1415,9 @@ class VirtualGen : public GenImpl<Value, VirtualGen<Value>> { ...@@ -1271,10 +1415,9 @@ class VirtualGen : public GenImpl<Value, VirtualGen<Value>> {
std::unique_ptr<const WrapperBase> wrapper_; std::unique_ptr<const WrapperBase> wrapper_;
public: public:
template<class SourceValue, template<class Self>
class Self> /* implicit */ VirtualGen(Self source)
/* implicit */ VirtualGen(const GenImpl<SourceValue, Self>& source) : wrapper_(new WrapperImpl<Self>(std::move(source)))
: wrapper_(new WrapperImpl<Self>(source.self()))
{ } { }
VirtualGen(VirtualGen&& source) VirtualGen(VirtualGen&& source)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment