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