Commit 27eb45f0 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook GitHub Bot

access::begin, access::end

Summary: Invokers for `begin` and `end` with `std::begin` and `std::end` in scope.

Reviewed By: ericniebler

Differential Revision: D26683890

fbshipit-source-id: 79e57b235c847b5bea29e2e6aac767bdfcef72e8
parent 0f3b490b
......@@ -20,9 +20,12 @@
#include <iterator>
#include <folly/Portability.h>
#include <folly/functional/Invoke.h>
namespace folly {
namespace access {
// mimic: std::size, C++17
struct size_fn {
template <typename C>
......@@ -82,4 +85,18 @@ struct data_fn {
};
FOLLY_INLINE_VARIABLE constexpr data_fn data{};
// begin
//
// Invokes unqualified begin with std::begin in scope.
FOLLY_CREATE_FREE_INVOKER(begin_fn, begin, std);
FOLLY_INLINE_VARIABLE constexpr begin_fn begin{};
// end
//
// Invokes unqualified end with std::end in scope.
FOLLY_CREATE_FREE_INVOKER(end_fn, end, std);
FOLLY_INLINE_VARIABLE constexpr end_fn end{};
} // namespace access
} // namespace folly
......@@ -25,6 +25,7 @@
#include <folly/Portability.h>
#include <folly/Traits.h>
#include <folly/Utility.h>
#include <folly/container/Access.h>
#include <folly/functional/Invoke.h>
namespace folly {
......@@ -33,10 +34,6 @@ namespace for_each_detail {
namespace adl {
/* using override */
using std::begin;
/* using override */
using std::end;
/* using override */
using std::get;
......@@ -50,14 +47,6 @@ template <std::size_t Index, typename Type>
auto adl_get(Type&& instance) -> decltype(get<Index>(std::declval<Type>())) {
return get<Index>(std::forward<Type>(instance));
}
template <typename Type>
auto adl_begin(Type&& instance) -> decltype(begin(instance)) {
return begin(instance);
}
template <typename Type>
auto adl_end(Type&& instance) -> decltype(end(instance)) {
return end(instance);
}
} // namespace adl
......@@ -111,8 +100,8 @@ struct IsTuple<EnableIfTuple<T>, T> : std::true_type {};
*/
template <typename Type, typename T = typename std::decay<Type>::type>
using EnableIfRange = void_t<
decltype(adl::adl_begin(std::declval<T>())),
decltype(adl::adl_end(std::declval<T>()))>;
decltype(access::begin(std::declval<T&>())),
decltype(access::end(std::declval<T&>()))>;
template <typename, typename T>
struct IsRange : std::false_type {};
template <typename T>
......@@ -166,8 +155,8 @@ LoopControl invoke_returning_loop_control(Func&& f, Args&&... a) {
*/
template <typename Sequence, typename Func>
void for_each_range_impl(index_constant<3>, Sequence&& range, Func& func) {
auto first = adl::adl_begin(range);
auto last = adl::adl_end(range);
auto first = access::begin(range);
auto last = access::end(range);
for (auto index = std::size_t{0}; first != last; ++index) {
auto next = std::next(first);
auto control = invoke_returning_loop_control(func, *first, index, first);
......@@ -273,7 +262,7 @@ void for_each_impl(TupleTag, Sequence&& range, Func& func) {
}
template <typename Sequence, typename Func>
void for_each_impl(RangeTag, Sequence&& range, Func& func) {
using iter = decltype(adl::adl_begin(std::declval<Sequence>()));
using iter = decltype(access::begin(std::declval<Sequence>()));
using type = decltype(*std::declval<iter>());
using tag = ForEachImplTag<Func, type, iter>;
static_assert(!std::is_same<tag, void>::value, "unknown invocability");
......@@ -286,7 +275,7 @@ decltype(auto) fetch_impl(IndexingTag, Sequence&& sequence, Index&& index) {
}
template <typename Sequence, typename Index>
decltype(auto) fetch_impl(BeginAddTag, Sequence&& sequence, Index index) {
return *(adl::adl_begin(std::forward<Sequence>(sequence)) + index);
return *(access::begin(std::forward<Sequence>(sequence)) + index);
}
template <typename Sequence, typename Index>
......@@ -295,7 +284,7 @@ decltype(auto) fetch_impl(TupleTag, Sequence&& sequence, Index index) {
}
template <typename Sequence, typename Index>
decltype(auto) fetch_impl(RangeTag, Sequence&& sequence, Index&& index) {
using iter = decltype(adl::adl_begin(std::declval<Sequence>()));
using iter = decltype(access::begin(std::declval<Sequence>()));
using iter_traits = std::iterator_traits<remove_cvref_t<iter>>;
using iter_cat = typename iter_traits::iterator_category;
using tag = std::conditional_t<
......
......@@ -25,77 +25,117 @@
class AccessTest : public testing::Test {};
TEST_F(AccessTest, size_vector) {
EXPECT_EQ(3, folly::size(std::vector<int>{1, 2, 3}));
EXPECT_EQ(3, folly::access::size(std::vector<int>{1, 2, 3}));
}
TEST_F(AccessTest, size_array) {
constexpr auto const a = std::array<int, 3>{{1, 2, 3}};
constexpr auto const size = folly::size(a);
constexpr auto const size = folly::access::size(a);
EXPECT_EQ(3, size);
}
TEST_F(AccessTest, size_carray) {
constexpr int const a[3] = {1, 2, 3};
constexpr auto const size = folly::size(a);
constexpr auto const size = folly::access::size(a);
EXPECT_EQ(3, size);
}
TEST_F(AccessTest, size_initializer_list) {
EXPECT_EQ(3, folly::size({1, 2, 3}));
EXPECT_EQ(3, folly::size(std::initializer_list<int>{1, 2, 3}));
EXPECT_EQ(3, folly::access::size({1, 2, 3}));
EXPECT_EQ(3, folly::access::size(std::initializer_list<int>{1, 2, 3}));
}
TEST_F(AccessTest, empty_vector) {
EXPECT_FALSE(folly::empty(std::vector<int>{1, 2, 3}));
EXPECT_TRUE(folly::empty(std::vector<int>{}));
EXPECT_FALSE(folly::access::empty(std::vector<int>{1, 2, 3}));
EXPECT_TRUE(folly::access::empty(std::vector<int>{}));
}
TEST_F(AccessTest, empty_array) {
{
constexpr auto const a = std::array<int, 3>{{1, 2, 3}};
constexpr auto const empty = folly::empty(a);
constexpr auto const empty = folly::access::empty(a);
EXPECT_FALSE(empty);
}
{
constexpr auto const a = std::array<int, 0>{{}};
constexpr auto const empty = folly::empty(a);
constexpr auto const empty = folly::access::empty(a);
EXPECT_TRUE(empty);
}
}
TEST_F(AccessTest, empty_carray) {
constexpr int const a[3] = {1, 2, 3};
constexpr auto const empty = folly::empty(a);
constexpr auto const empty = folly::access::empty(a);
EXPECT_FALSE(empty);
// zero-length arrays are not allowed in the language
}
TEST_F(AccessTest, empty_initializer_list) {
EXPECT_FALSE(folly::empty({1, 2, 3}));
EXPECT_FALSE(folly::empty(std::initializer_list<int>{1, 2, 3}));
EXPECT_TRUE(folly::empty(std::initializer_list<int>{}));
EXPECT_FALSE(folly::access::empty({1, 2, 3}));
EXPECT_FALSE(folly::access::empty(std::initializer_list<int>{1, 2, 3}));
EXPECT_TRUE(folly::access::empty(std::initializer_list<int>{}));
}
TEST_F(AccessTest, data_vector) {
EXPECT_EQ(1, *folly::data(std::vector<int>{1, 2, 3}));
EXPECT_EQ(1, *folly::access::data(std::vector<int>{1, 2, 3}));
auto v = std::vector<int>{1, 2, 3};
*folly::data(v) = 4;
*folly::access::data(v) = 4;
EXPECT_EQ(4, v[0]);
}
TEST_F(AccessTest, data_array) {
constexpr auto const a = std::array<int, 3>{{1, 2, 3}};
auto const data = folly::data(a); // not constexpr until C++17
auto const data = folly::access::data(a); // not constexpr until C++17
EXPECT_EQ(1, *data);
}
TEST_F(AccessTest, data_carray) {
constexpr int const a[3] = {1, 2, 3};
auto const data = folly::data(a); // not constexpr until C++17
auto const data = folly::access::data(a); // not constexpr until C++17
EXPECT_EQ(1, *data);
}
TEST_F(AccessTest, data_initializer_list) {
EXPECT_EQ(1, *folly::data({1, 2, 3}));
EXPECT_EQ(1, *folly::data(std::initializer_list<int>{1, 2, 3}));
EXPECT_EQ(1, *folly::access::data({1, 2, 3}));
EXPECT_EQ(1, *folly::access::data(std::initializer_list<int>{1, 2, 3}));
}
TEST_F(AccessTest, begin_vector) {
auto v = std::vector<int>{1, 2, 3};
EXPECT_EQ(v.begin(), folly::access::begin(v));
}
TEST_F(AccessTest, begin_array) {
constexpr auto const a = std::array<int, 3>{{1, 2, 3}};
EXPECT_EQ(a.begin(), folly::access::begin(a));
}
TEST_F(AccessTest, begin_carray) {
constexpr int const a[3] = {1, 2, 3};
EXPECT_EQ(a + 0, folly::access::begin(a));
}
TEST_F(AccessTest, begin_initializer_list) {
auto i = std::initializer_list<int>{1, 2, 3};
EXPECT_EQ(i.begin(), folly::access::begin(i));
}
TEST_F(AccessTest, end_vector) {
auto v = std::vector<int>{1, 2, 3};
EXPECT_EQ(v.end(), folly::access::end(v));
}
TEST_F(AccessTest, end_array) {
constexpr auto const a = std::array<int, 3>{{1, 2, 3}};
EXPECT_EQ(a.end(), folly::access::end(a));
}
TEST_F(AccessTest, end_carray) {
constexpr int const a[3] = {1, 2, 3};
EXPECT_EQ(a + 3, folly::access::end(a));
}
TEST_F(AccessTest, end_initializer_list) {
auto i = std::initializer_list<int>{1, 2, 3};
EXPECT_EQ(i.end(), folly::access::end(i));
}
......@@ -512,10 +512,8 @@ auto collectAllWindowed(InputRange awaitables, std::size_t maxConcurrency)
}
};
using std::begin;
using std::end;
auto iter = begin(awaitables);
const auto iterEnd = end(awaitables);
auto iter = access::begin(awaitables);
const auto iterEnd = access::end(awaitables);
using iterator_t = decltype(iter);
using awaitable_t = typename std::iterator_traits<iterator_t>::value_type;
......@@ -648,10 +646,8 @@ auto collectAllWindowed(InputRange awaitables, std::size_t maxConcurrency)
}
};
using std::begin;
using std::end;
auto iter = begin(awaitables);
const auto iterEnd = end(awaitables);
auto iter = access::begin(awaitables);
const auto iterEnd = access::end(awaitables);
using iterator_t = decltype(iter);
using awaitable_t = typename std::iterator_traits<iterator_t>::value_type;
......@@ -807,10 +803,8 @@ auto collectAllTryWindowed(InputRange awaitables, std::size_t maxConcurrency)
const Executor::KeepAlive<> executor = co_await co_current_executor;
const CancellationToken& cancelToken = co_await co_current_cancellation_token;
using std::begin;
using std::end;
auto iter = begin(awaitables);
const auto iterEnd = end(awaitables);
auto iter = access::begin(awaitables);
const auto iterEnd = access::end(awaitables);
using iterator_t = decltype(iter);
using awaitable_t = typename std::iterator_traits<iterator_t>::value_type;
......
......@@ -18,6 +18,7 @@
#include <folly/Try.h>
#include <folly/Unit.h>
#include <folly/container/Access.h>
#include <folly/experimental/coro/Coroutine.h>
#include <folly/experimental/coro/Task.h>
#include <folly/experimental/coro/ViaIfAsync.h>
......@@ -53,7 +54,7 @@ using collect_all_try_range_component_t =
collect_all_try_component_t<SemiAwaitable>;
template <typename Range>
using range_iterator_t = decltype(std::begin(std::declval<Range&>()));
using range_iterator_t = decltype(access::begin(std::declval<Range&>()));
template <typename Iterator>
using iterator_reference_t = typename std::iterator_traits<Iterator>::reference;
......
......@@ -188,7 +188,8 @@ class CopiedSource
template <class SourceContainer>
explicit CopiedSource(const SourceContainer& container)
: copy_(new Container(begin(container), end(container))) {}
: copy_(new Container(access::begin(container), access::end(container))) {
}
explicit CopiedSource(Container&& container)
: copy_(new Container(std::move(container))) {}
......
......@@ -29,6 +29,7 @@
#include <folly/Optional.h>
#include <folly/Range.h>
#include <folly/Utility.h>
#include <folly/container/Access.h>
#include <folly/gen/Core.h>
/**
......@@ -244,7 +245,7 @@ struct FBounded;
template <class Container>
struct ValueTypeOfRange {
public:
using RefType = decltype(*std::begin(std::declval<Container&>()));
using RefType = decltype(*access::begin(std::declval<Container&>()));
using StorageType = typename std::decay<RefType>::type;
};
......
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