From 0f14503ec3cee25f5425588c83347794c9afb429 Mon Sep 17 00:00:00 2001 From: Yedidya Feldblum Date: Fri, 10 Nov 2017 16:03:47 -0800 Subject: [PATCH] Backport C++17 container access functions: size, empty, data Summary: [Folly] Backport C++17 container access functions: `size`, `empty`, `data`. Reviewed By: Orvid Differential Revision: D6301986 fbshipit-source-id: 65c31df68b7743d5ed4a2cf2419586b862683c48 --- CMakeLists.txt | 1 + folly/Makefile.am | 1 + folly/container/Access.h | 89 ++++++++++++++++++++++++ folly/container/test/AccessTest.cpp | 101 ++++++++++++++++++++++++++++ folly/test/Makefile.am | 3 + 5 files changed, 195 insertions(+) create mode 100644 folly/container/Access.h create mode 100644 folly/container/test/AccessTest.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 518e3df6..699489bf 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -331,6 +331,7 @@ if (BUILD_TESTS) TEST compression_test SOURCES CompressionTest.cpp DIRECTORY container/test/ + TEST access_test SOURCES AccessTest.cpp TEST array_test SOURCES ArrayTest.cpp TEST enumerate_test SOURCES EnumerateTest.cpp TEST evicting_cache_map_test SOURCES EvictingCacheMapTest.cpp diff --git a/folly/Makefile.am b/folly/Makefile.am index 83f79c20..0639ff90 100644 --- a/folly/Makefile.am +++ b/folly/Makefile.am @@ -56,6 +56,7 @@ nobase_follyinclude_HEADERS = \ concurrency/ConcurrentHashMap.h \ concurrency/CoreCachedSharedPtr.h \ concurrency/detail/ConcurrentHashMap-detail.h \ + container/Access.h \ container/Array.h \ container/Iterator.h \ container/Enumerate.h \ diff --git a/folly/container/Access.h b/folly/container/Access.h new file mode 100644 index 00000000..8116c194 --- /dev/null +++ b/folly/container/Access.h @@ -0,0 +1,89 @@ +/* + * Copyright 2017 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +/** + * include or backport: + * * std::size + * * std::empty + * * std::data + */ + +#if __cpp_lib_nonmember_container_access >= 201411 || _MSC_VER + +namespace folly { + +/* using override */ using std::size; +/* using override */ using std::empty; +/* using override */ using std::data; + +} + +#else + +namespace folly { + +// mimic: std::size, C++17 +template +constexpr auto size(C const& c) -> decltype(c.size()) { + return c.size(); +} +template +constexpr std::size_t size(T const (&)[N]) noexcept { + return N; +} + +// mimic: std::empty, C++17 +template +constexpr auto empty(C const& c) -> decltype(c.empty()) { + return c.empty(); +} +template +constexpr bool empty(T const (&)[N]) noexcept { + // while zero-length arrays are not allowed in the language, some compilers + // may permit them in some cases + return N == 0; +} +template +constexpr bool empty(std::initializer_list il) noexcept { + return il.size() == 0; +} + +// mimic: std::data, C++17 +template +constexpr auto data(C& c) -> decltype(c.data()) { + return c.data(); +} +template +constexpr auto data(C const& c) -> decltype(c.data()) { + return c.data(); +} +template +constexpr T* data(T (&a)[N]) noexcept { + return a; +} +template +constexpr E const* data(std::initializer_list il) noexcept { + return il.begin(); +} + +} + +#endif diff --git a/folly/container/test/AccessTest.cpp b/folly/container/test/AccessTest.cpp new file mode 100644 index 00000000..56ae7453 --- /dev/null +++ b/folly/container/test/AccessTest.cpp @@ -0,0 +1,101 @@ +/* + * Copyright 2017 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include + +#include + +class AccessTest : public testing::Test {}; + +TEST_F(AccessTest, size_vector) { + EXPECT_EQ(3, folly::size(std::vector{1, 2, 3})); +} + +TEST_F(AccessTest, size_array) { + constexpr auto const a = std::array{{1, 2, 3}}; + constexpr auto const size = folly::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); + 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{1, 2, 3})); +} + +TEST_F(AccessTest, empty_vector) { + EXPECT_FALSE(folly::empty(std::vector{1, 2, 3})); + EXPECT_TRUE(folly::empty(std::vector{})); +} + +TEST_F(AccessTest, empty_array) { + { + constexpr auto const a = std::array{{1, 2, 3}}; + constexpr auto const empty = folly::empty(a); + EXPECT_FALSE(empty); + } + { + constexpr auto const a = std::array{{}}; + constexpr auto const empty = folly::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); + 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{1, 2, 3})); + EXPECT_TRUE(folly::empty(std::initializer_list{})); +} + +TEST_F(AccessTest, data_vector) { + EXPECT_EQ(1, *folly::data(std::vector{1, 2, 3})); + auto v = std::vector{1, 2, 3}; + *folly::data(v) = 4; + EXPECT_EQ(4, v[0]); +} + +TEST_F(AccessTest, data_array) { + constexpr auto const a = std::array{{1, 2, 3}}; + auto const data = folly::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 + 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{1, 2, 3})); +} diff --git a/folly/test/Makefile.am b/folly/test/Makefile.am index 697fd742..a19368d8 100644 --- a/folly/test/Makefile.am +++ b/folly/test/Makefile.am @@ -81,6 +81,9 @@ endif sorted_vector_types_test_SOURCES = sorted_vector_test.cpp sorted_vector_types_test_LDADD = libfollytestmain.la +container_access_test_SOURCES = ../container/test/AccessTets.cpp +container_access_test_LDADD = libfollytestmain.la +TESTS += container_access_test foreach_test_SOURCES = ../container/test/ForeachTest.cpp foreach_test_LDADD = libfollytestmain.la -- 2.34.1