Commit 60b6e844 authored by Adam Simpkins's avatar Adam Simpkins Committed by Facebook Github Bot

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
parent e1a26ff9
...@@ -26,12 +26,13 @@ ...@@ -26,12 +26,13 @@
#include <folly/portability/Constexpr.h> #include <folly/portability/Constexpr.h>
#include <folly/portability/String.h> #include <folly/portability/String.h>
#include <algorithm>
#include <boost/operators.hpp> #include <boost/operators.hpp>
#include <glog/logging.h>
#include <algorithm>
#include <array>
#include <climits> #include <climits>
#include <cstddef> #include <cstddef>
#include <cstring> #include <cstring>
#include <glog/logging.h>
#include <iosfwd> #include <iosfwd>
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
...@@ -332,6 +333,30 @@ public: ...@@ -332,6 +333,30 @@ public:
e_(other.end()) { 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<char, N> or a std::array<const char, N>
*/
template <
class T,
size_t N,
typename = typename std::enable_if<
std::is_convertible<const T*, Iter>::value>::type>
constexpr explicit Range(const std::array<T, N>& 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<std::is_convertible<T*, Iter>::value>::type>
constexpr explicit Range(std::array<T, N>& array)
: b_{array.empty() ? nullptr : &array.at(0)},
e_{array.empty() ? nullptr : &array.at(0) + N} {}
Range& operator=(const Range& rhs) & = default; Range& operator=(const Range& rhs) & = default;
Range& operator=(Range&& rhs) & = default; Range& operator=(Range&& rhs) & = default;
...@@ -907,8 +932,7 @@ constexpr Range<T*> range(T (&array)[n]) { ...@@ -907,8 +932,7 @@ constexpr Range<T*> range(T (&array)[n]) {
template <class T, size_t n> template <class T, size_t n>
constexpr Range<const T*> range(const std::array<T, n>& array) { constexpr Range<const T*> range(const std::array<T, n>& array) {
using r = Range<const T*>; return Range<const T*>{array};
return array.empty() ? r{} : r(&array.at(0), &array.at(0) + n);
} }
typedef Range<const char*> StringPiece; typedef Range<const char*> StringPiece;
......
...@@ -1298,6 +1298,40 @@ TEST(Range, Constructors) { ...@@ -1298,6 +1298,40 @@ TEST(Range, Constructors) {
EXPECT_EQ(subpiece1.end(), subpiece2.end()); EXPECT_EQ(subpiece1.end(), subpiece2.end());
} }
TEST(Range, ArrayConstructors) {
auto charArray = std::array<char, 4>{{'t', 'e', 's', 't'}};
auto constCharArray = std::array<char, 6>{{'f', 'o', 'o', 'b', 'a', 'r'}};
auto emptyArray = std::array<char, 0>{};
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<int, 4> numArray = {{3, 17, 1, 9}};
constexpr auto numRange = Range<const int*>{numArray};
EXPECT_EQ(17, numRange[1]);
static constexpr std::array<int, 0> emptyNumArray{};
constexpr auto emptyNumRange = Range<const int*>{emptyNumArray};
EXPECT_EQ(0, emptyNumRange.size());
}
TEST(Range, ConstexprAccessors) { TEST(Range, ConstexprAccessors) {
constexpr StringPiece piece = range("hello"); constexpr StringPiece piece = range("hello");
static_assert(piece.size() == 6u, ""); static_assert(piece.size() == 6u, "");
......
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