From: Adam Simpkins Date: Sat, 11 Feb 2017 01:11:44 +0000 (-0800) Subject: add Range constructors from std::array X-Git-Tag: v2017.03.06.00~40 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=60b6e844c5c581d9e8004e20a3409b6b4430fd9d;p=folly.git add Range constructors from std::array Summary: Add explicit constructors to create Range objects referring to the contents of a std::array. D4165608 previously added a folly::range() factory function to create Ranges around const arrays. However, it did not support non-const arrays. However, providing this as a constructor seems better. This new constructor does not appear ambiguous with any existing constructors, and a constructor allows for more natural support of non-const arrays: the caller can explicitly indicate if they want to construct a Range to const or non-const data in this case. Reviewed By: yfeldblum Differential Revision: D4523515 fbshipit-source-id: c1a262f9e8f76907d87d80b03f252576506e70ab --- diff --git a/folly/Range.h b/folly/Range.h index d205a7b3..bfbb4eb0 100644 --- a/folly/Range.h +++ b/folly/Range.h @@ -26,12 +26,13 @@ #include #include -#include #include +#include +#include +#include #include #include #include -#include #include #include #include @@ -332,6 +333,30 @@ public: e_(other.end()) { } + /** + * Allow explicit construction of Range() from a std::array of a + * convertible type. + * + * For instance, this allows constructing StringPiece from a + * std::array or a std::array + */ + template < + class T, + size_t N, + typename = typename std::enable_if< + std::is_convertible::value>::type> + constexpr explicit Range(const std::array& array) + : b_{array.empty() ? nullptr : &array.at(0)}, + e_{array.empty() ? nullptr : &array.at(0) + N} {} + template < + class T, + size_t N, + typename = + typename std::enable_if::value>::type> + constexpr explicit Range(std::array& array) + : b_{array.empty() ? nullptr : &array.at(0)}, + e_{array.empty() ? nullptr : &array.at(0) + N} {} + Range& operator=(const Range& rhs) & = default; Range& operator=(Range&& rhs) & = default; @@ -907,8 +932,7 @@ constexpr Range range(T (&array)[n]) { template constexpr Range range(const std::array& array) { - using r = Range; - return array.empty() ? r{} : r(&array.at(0), &array.at(0) + n); + return Range{array}; } typedef Range StringPiece; diff --git a/folly/test/RangeTest.cpp b/folly/test/RangeTest.cpp index a7d61f4a..d4f65865 100644 --- a/folly/test/RangeTest.cpp +++ b/folly/test/RangeTest.cpp @@ -1298,6 +1298,40 @@ TEST(Range, Constructors) { EXPECT_EQ(subpiece1.end(), subpiece2.end()); } +TEST(Range, ArrayConstructors) { + auto charArray = std::array{{'t', 'e', 's', 't'}}; + auto constCharArray = std::array{{'f', 'o', 'o', 'b', 'a', 'r'}}; + auto emptyArray = std::array{}; + + auto sp1 = StringPiece{charArray}; + EXPECT_EQ(4, sp1.size()); + EXPECT_EQ(charArray.data(), sp1.data()); + + auto sp2 = StringPiece(constCharArray); + EXPECT_EQ(6, sp2.size()); + EXPECT_EQ(constCharArray.data(), sp2.data()); + + auto msp = MutableStringPiece(charArray); + EXPECT_EQ(4, msp.size()); + EXPECT_EQ(charArray.data(), msp.data()); + + auto esp = StringPiece(emptyArray); + EXPECT_EQ(0, esp.size()); + EXPECT_EQ(nullptr, esp.data()); + + auto emsp = MutableStringPiece(emptyArray); + EXPECT_EQ(0, emsp.size()); + EXPECT_EQ(nullptr, emsp.data()); + + static constexpr std::array numArray = {{3, 17, 1, 9}}; + constexpr auto numRange = Range{numArray}; + EXPECT_EQ(17, numRange[1]); + + static constexpr std::array emptyNumArray{}; + constexpr auto emptyNumRange = Range{emptyNumArray}; + EXPECT_EQ(0, emptyNumRange.size()); +} + TEST(Range, ConstexprAccessors) { constexpr StringPiece piece = range("hello"); static_assert(piece.size() == 6u, "");