void foreach(Body&& body) const {
source_.foreach([&](Value value) {
if (value) {
- return body(*value);
+ return body(*std::forward<Value>(value));
}
});
}
bool apply(Handler&& handler) const {
return source_.apply([&](Value value) -> bool {
if (value) {
- return handler(*value);
+ return handler(*std::forward<Value>(value));
}
return true;
});
template <class Body>
void foreach(Body&& body) const {
source_.foreach([&](Value value) {
- return body(&value);
+ return body(&std::forward<Value>(value));
});
}
template <class Handler>
bool apply(Handler&& handler) const {
return source_.apply([&](Value value) -> bool {
- return handler(&value);
+ return handler(&std::forward<Value>(value));
});
}
Selector selector_;
Comparer comparer_;
+ template <typename T>
+ const T& asConst(const T& t) const {
+ return t;
+ }
+
public:
Min() = default;
Optional<StorageType> min;
Optional<Key> minKey;
source | [&](Value v) {
- Key key = selector_(std::forward<Value>(v));
+ Key key = selector_(asConst(v)); // so that selector_ cannot mutate v
if (!minKey.hasValue() || comparer_(key, minKey.value())) {
- minKey = key;
+ minKey = std::move(key);
min = std::forward<Value>(v);
}
};
#include <folly/FBVector.h>
#include <folly/MapUtil.h>
#include <folly/Memory.h>
+#include <folly/String.h>
#include <folly/dynamic.h>
-#include <folly/gen/Base.h>
#include <folly/experimental/TestUtil.h>
+#include <folly/gen/Base.h>
using namespace folly::gen;
using namespace folly;
}
}
+namespace {
+struct DereferenceWrapper {
+ string data;
+ string& operator*() & {
+ return data;
+ }
+ string&& operator*() && {
+ return std::move(data);
+ }
+ explicit operator bool() {
+ return true;
+ }
+};
+bool operator==(const DereferenceWrapper& a, const DereferenceWrapper& b) {
+ return a.data == b.data;
+}
+void PrintTo(const DereferenceWrapper& a, std::ostream* o) {
+ *o << "Wrapper{\"" << cEscape<string>(a.data) << "\"}";
+}
+}
+
+TEST(Gen, DereferenceWithLValueRef) {
+ auto original = vector<DereferenceWrapper>{{"foo"}, {"bar"}};
+ auto copy = original;
+ auto expected = vector<string>{"foo", "bar"};
+ auto actual = from(original) | dereference | as<vector>();
+ EXPECT_EQ(expected, actual);
+ EXPECT_EQ(copy, original);
+}
+
+TEST(Gen, DereferenceWithRValueRef) {
+ auto original = vector<DereferenceWrapper>{{"foo"}, {"bar"}};
+ auto empty = vector<DereferenceWrapper>{{}, {}};
+ auto expected = vector<string>{"foo", "bar"};
+ auto actual = from(original) | move | dereference | as<vector>();
+ EXPECT_EQ(expected, actual);
+ EXPECT_EQ(empty, original);
+}
+
TEST(Gen, Indirect) {
vector<int> vs{1};
EXPECT_EQ(&vs[0], from(vs) | indirect | first | unwrap);