Commit ca7e6f1b authored by Tom Jackson's avatar Tom Jackson Committed by Sara Golemon

dereference

Summary:
For dealing with sequences of pointers. Works with pointer wrappers,
and filters out nullptrs, see tests.

Test Plan: Unit tests

Reviewed By: tulloch@fb.com

FB internal diff: D914069
parent 52479853
......@@ -1955,6 +1955,65 @@ class Cycle : public Operator<Cycle> {
}
};
/**
* Dereference - For dereferencing a sequence of pointers while filtering out
* null pointers.
*
* This type is usually used through the 'dereference' static value, like:
*
* auto refs = from(ptrs) | dereference;
*/
class Dereference : public Operator<Dereference> {
public:
Dereference() {}
template<class Value,
class Source,
class Result = decltype(*std::declval<Value>())>
class Generator : public GenImpl<Result, Generator<Value, Source, Result>> {
Source source_;
public:
explicit Generator(Source source)
: source_(std::move(source)) {}
template<class Body>
void foreach(Body&& body) const {
source_.foreach([&](Value value) {
if (value) {
return body(*value);
}
});
}
template<class Handler>
bool apply(Handler&& handler) const {
return source_.apply([&](Value value) -> bool {
if (value) {
return handler(*value);
}
return true;
});
}
// not actually infinite, since an empty generator will end the cycles.
static constexpr bool infinite = Source::infinite;
};
template<class Source,
class Value,
class Gen = Generator<Value, Source>>
Gen compose(GenImpl<Value, Source>&& source) const {
return Gen(std::move(source.self()));
}
template<class Source,
class Value,
class Gen = Generator<Value, Source>>
Gen compose(const GenImpl<Value, Source>& source) const {
return Gen(source.self());
}
};
} //::detail
/**
......@@ -2067,6 +2126,8 @@ static const detail::RangeConcat rconcat;
*/
static const detail::Cycle cycle;
static const detail::Dereference dereference;
inline detail::Take take(size_t count) {
return detail::Take(count);
}
......
......@@ -312,6 +312,8 @@ class Cycle;
class Batch;
class Dereference;
/*
* Sinks
*/
......
......@@ -20,26 +20,29 @@
#include <random>
#include <set>
#include <vector>
#include "folly/experimental/Gen.h"
#include "folly/experimental/StringGen.h"
#include "folly/experimental/CombineGen.h"
#include "folly/experimental/FileGen.h"
#include "folly/experimental/TestUtil.h"
#include "folly/FBString.h"
#include "folly/FBVector.h"
#include "folly/Format.h"
#include "folly/MapUtil.h"
#include "folly/Memory.h"
#include "folly/dynamic.h"
#include "folly/experimental/CombineGen.h"
#include "folly/experimental/FileGen.h"
#include "folly/experimental/Gen.h"
#include "folly/experimental/StringGen.h"
#include "folly/experimental/TestUtil.h"
using namespace folly::gen;
using namespace folly;
using std::make_tuple;
using std::ostream;
using std::pair;
using std::set;
using std::unique_ptr;
using std::vector;
using std::string;
using std::tuple;
using std::make_tuple;
using std::unique_ptr;
using std::vector;
#define EXPECT_SAME(A, B) \
static_assert(std::is_same<A, B>::value, "Mismatched: " #A ", " #B)
......@@ -1038,6 +1041,60 @@ TEST(Gen, Cycle) {
}
}
TEST(Gen, Dereference) {
{
const int x = 4, y = 2;
auto s = from<const int*>({&x, nullptr, &y});
EXPECT_EQ(6, s | dereference | sum);
}
{
vector<int> a { 1, 2 };
vector<int> b { 3, 4 };
vector<vector<int>*> pv { &a, nullptr, &b };
from(pv)
| dereference
| [&](vector<int>& v) {
v.push_back(5);
};
EXPECT_EQ(3, a.size());
EXPECT_EQ(3, b.size());
EXPECT_EQ(5, a.back());
EXPECT_EQ(5, b.back());
}
{
vector<std::map<int, int>> maps {
{
{ 2, 31 },
{ 3, 41 },
},
{
{ 3, 52 },
{ 4, 62 },
},
{
{ 4, 73 },
{ 5, 83 },
},
};
EXPECT_EQ(
93,
from(maps)
| map([](std::map<int, int>& m) {
return get_ptr(m, 3);
})
| dereference
| sum);
}
{
vector<unique_ptr<int>> ups;
ups.emplace_back(new int(3));
ups.emplace_back();
ups.emplace_back(new int(7));
EXPECT_EQ(10, from(ups) | dereference | sum);
EXPECT_EQ(10, from(ups) | move | dereference | sum);
}
}
TEST(StringGen, Split) {
auto collect = eachTo<std::string>() | as<vector>();
{
......
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