From: Mark Isaacson Date: Tue, 19 Apr 2016 07:46:56 +0000 (-0700) Subject: Add make_array to folly X-Git-Tag: 2016.07.26~343 X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=commitdiff_plain;h=1fb83fbce666105e62cbfb36851f6886f064ada4 Add make_array to folly Summary: This function is being proposed in WG21, the C++ standards body for inclusion in the STL via the Library Fundamentals v2 TS. Using the normal constructor for a std::array with an initializer list introduces a source of coupling between the # of elements you put in the initializer list and the size of the array you specify as a template argument. Worse still, if you put less things in the initializer list than the template argument specifies, it doesn't warn you that you've probably made a pretty devious and subtle error. With this function your array size will always be the same as the # of things you actually put in it. What's more, in some cases this can deduce the type of the elements as well. Reviewed By: yfeldblum Differential Revision: D3164432 fb-gh-sync-id: beceaae2ee01cd5f93dec86cf36efdb78a28b4a3 fbshipit-source-id: beceaae2ee01cd5f93dec86cf36efdb78a28b4a3 --- diff --git a/folly/Array.h b/folly/Array.h new file mode 100644 index 00000000..77faafe3 --- /dev/null +++ b/folly/Array.h @@ -0,0 +1,59 @@ +/* + * Copyright 2016 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 +#include + +namespace folly { + +namespace array_detail { +template +struct is_ref_wrapper : std::false_type {}; +template +struct is_ref_wrapper> : std::true_type {}; + +template +using not_ref_wrapper = + folly::Negation::type>>; + +template +struct return_type_helper { + using type = D; +}; +template +struct return_type_helper { + static_assert( + folly::Conjunction...>::value, + "TList cannot contain reference_wrappers when D is void"); + using type = typename std::common_type::type; +}; + +template +using return_type = std:: + array::type, sizeof...(TList)>; +} // !array_detail + +template +constexpr array_detail::return_type make_array(TList&&... t) { + using value_type = + typename array_detail::return_type_helper::type; + return {static_cast(std::forward(t))...}; +} + +} // !folly diff --git a/folly/Makefile.am b/folly/Makefile.am index d9e8e771..5eb27680 100644 --- a/folly/Makefile.am +++ b/folly/Makefile.am @@ -25,6 +25,7 @@ nobase_follyinclude_HEADERS = \ ApplyTuple.h \ Arena.h \ Arena-inl.h \ + Array.h \ Assume.h \ AtomicBitSet.h \ AtomicHashArray.h \ diff --git a/folly/Traits.h b/folly/Traits.h index f34dc748..598a63a7 100644 --- a/folly/Traits.h +++ b/folly/Traits.h @@ -132,6 +132,25 @@ template struct IsZeroInitializable traits_detail::has_true_IsZeroInitializable::value > {}; +template +struct Conjunction : std::true_type {}; +template +struct Conjunction : T {}; +template +struct Conjunction + : std::conditional, T>::type {}; + +template +struct Disjunction : std::false_type {}; +template +struct Disjunction : T {}; +template +struct Disjunction + : std::conditional>::type {}; + +template +struct Negation : std::integral_constant {}; + } // namespace folly /** diff --git a/folly/test/ArrayTest.cpp b/folly/test/ArrayTest.cpp new file mode 100644 index 00000000..2bfc73a8 --- /dev/null +++ b/folly/test/ArrayTest.cpp @@ -0,0 +1,71 @@ +/* + * Copyright 2016 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 + +using namespace std; +using folly::make_array; + +TEST(make_array, base_case) { + auto arr = make_array(); + static_assert( + is_same::value, + "Wrong array type"); + EXPECT_EQ(arr.size(), 0); +} + +TEST(make_array, deduce_size_primitive) { + auto arr = make_array(1, 2, 3, 4, 5); + static_assert( + is_same::value, + "Wrong array type"); + EXPECT_EQ(arr.size(), 5); +} + +TEST(make_array, deduce_size_class) { + auto arr = make_array(string{"foo"}, string{"bar"}); + static_assert( + is_same::value, + "Wrong array type"); + EXPECT_EQ(arr.size(), 2); + EXPECT_EQ(arr[1], "bar"); +} + +TEST(make_array, deduce_everything) { + auto arr = make_array(string{"foo"}, string{"bar"}); + static_assert( + is_same::value, + "Wrong array type"); + EXPECT_EQ(arr.size(), 2); + EXPECT_EQ(arr[1], "bar"); +} + +TEST(make_array, fixed_common_type) { + auto arr = make_array(1.0, 2.5f, 3, 4, 5); + static_assert( + is_same::value, + "Wrong array type"); + EXPECT_EQ(arr.size(), 5); +} + +TEST(make_array, deduced_common_type) { + auto arr = make_array(1.0, 2.5f, 3, 4, 5); + static_assert( + is_same::value, + "Wrong array type"); + EXPECT_EQ(arr.size(), 5); +} diff --git a/folly/test/Makefile.am b/folly/test/Makefile.am index 71fe7a80..229efaf5 100644 --- a/folly/test/Makefile.am +++ b/folly/test/Makefile.am @@ -37,6 +37,10 @@ spin_lock_test_SOURCES = SpinLockTest.cpp spin_lock_test_LDADD = libfollytestmain.la TESTS += spin_lock_test +array_test_SOURCES = ArrayTest.cpp +array_test_LDADD = libfollytestmain.la +TESTS += array_test + if RUN_ARCH_SPECIFIC_TESTS small_locks_test_SOURCES = SmallLocksTest.cpp small_locks_test_LDADD = libfollytestmain.la diff --git a/folly/test/TraitsTest.cpp b/folly/test/TraitsTest.cpp index 82cded67..453c29ed 100644 --- a/folly/test/TraitsTest.cpp +++ b/folly/test/TraitsTest.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -84,6 +85,25 @@ TEST(Traits, bitAndInit) { EXPECT_FALSE(IsZeroInitializable>::value); } +TEST(Trait, logicOperators) { + static_assert(Conjunction::value, ""); + static_assert(!Conjunction::value, ""); + static_assert(is_same::type, true_type>::value, ""); + static_assert(is_same::type, false_type>::value, ""); + static_assert(Conjunction::value, ""); + static_assert(!Conjunction::value, ""); + + static_assert(Disjunction::value, ""); + static_assert(!Disjunction::value, ""); + static_assert(is_same::type, true_type>::value, ""); + static_assert(is_same::type, false_type>::value, ""); + static_assert(Disjunction::value, ""); + static_assert(Disjunction::value, ""); + + static_assert(!Negation::value, ""); + static_assert(Negation::value, ""); +} + TEST(Traits, is_negative) { EXPECT_TRUE(folly::is_negative(-1)); EXPECT_FALSE(folly::is_negative(0));