Let folly::range be constexpr
authorYedidya Feldblum <yfeldblum@fb.com>
Sun, 6 Nov 2016 21:09:44 +0000 (13:09 -0800)
committerFacebook Github Bot <facebook-github-bot-bot@fb.com>
Sun, 6 Nov 2016 21:23:28 +0000 (13:23 -0800)
Summary:
[Folly] Let `folly::range` be `constexpr`.

It will be useful to have this helper function be `constexpr` to support further compile-time code.

Reviewed By: juchem

Differential Revision: D4135943

fbshipit-source-id: a62be93f9e492ca302130d1a3b190ed4b69f7a80

folly/Range.h
folly/test/RangeTest.cpp

index 97a7f1d082ba213f6c2025a855199bb171bdd00d..06123d346611b3f836f259fb96db455be20f612a 100644 (file)
@@ -864,7 +864,7 @@ void swap(Range<T>& lhs, Range<T>& rhs) {
  * Create a range from two iterators, with type deduction.
  */
 template <class Iter>
-Range<Iter> range(Iter first, Iter last) {
+constexpr Range<Iter> range(Iter first, Iter last) {
   return Range<Iter>(first, last);
 }
 
@@ -872,15 +872,16 @@ Range<Iter> range(Iter first, Iter last) {
  * Creates a range to reference the contents of a contiguous-storage container.
  */
 // Use pointers for types with '.data()' member
-template <class Collection,
-          class T = typename std::remove_pointer<
-              decltype(std::declval<Collection>().data())>::type>
-Range<T*> range(Collection&& v) {
+template <
+    class Collection,
+    class T = typename std::remove_pointer<
+        decltype(std::declval<Collection>().data())>::type>
+constexpr Range<T*> range(Collection&& v) {
   return Range<T*>(v.data(), v.data() + v.size());
 }
 
 template <class T, size_t n>
-Range<T*> range(T (&array)[n]) {
+constexpr Range<T*> range(T (&array)[n]) {
   return Range<T*>(array, array + n);
 }
 
index ef4c1e1e341d0ea07145b4760b3999eec7f02e98..dc7e4ff0842b5470d9eaf77aa85099685e4c5612 100644 (file)
@@ -293,9 +293,9 @@ TEST(StringPiece, InvalidRange) {
   EXPECT_THROW(a.subpiece(6), std::out_of_range);
 }
 
-constexpr const char* helloArray = "hello";
-
 TEST(StringPiece, Constexpr) {
+  constexpr const char* helloArray = "hello";
+
   constexpr StringPiece hello1("hello");
   EXPECT_EQ("hello", hello1);
   static_assert(hello1.size() == 5, "hello size should be 5 at compile time");
@@ -1098,6 +1098,47 @@ TEST(RangeFunc, CArray) {
   testRangeFunc(x, 4);
 }
 
+TEST(RangeFunc, ConstexprCArray) {
+  static constexpr const int numArray[4] = {3, 17, 1, 9};
+  constexpr const auto numArrayRange = range(numArray);
+  EXPECT_EQ(17, numArrayRange[1]);
+  constexpr const auto numArrayRangeSize = numArrayRange.size();
+  EXPECT_EQ(4, numArrayRangeSize);
+}
+
+TEST(RangeFunc, ConstexprIteratorPair) {
+  static constexpr const int numArray[4] = {3, 17, 1, 9};
+  constexpr const auto numPtr = static_cast<const int*>(numArray);
+  constexpr const auto numIterRange = range(numPtr + 1, numPtr + 3);
+  EXPECT_EQ(1, numIterRange[1]);
+  constexpr const auto numIterRangeSize = numIterRange.size();
+  EXPECT_EQ(2, numIterRangeSize);
+}
+
+TEST(RangeFunc, ConstexprCollection) {
+  class IntCollection {
+   public:
+    constexpr IntCollection(const int* d, size_t s) : data_(d), size_(s) {}
+    constexpr const int* data() const {
+      return data_;
+    }
+    constexpr size_t size() const {
+      return size_;
+    }
+
+   private:
+    const int* data_;
+    size_t size_;
+  };
+  static constexpr const int numArray[4] = {3, 17, 1, 9};
+  constexpr const auto numPtr = static_cast<const int*>(numArray);
+  constexpr const auto numColl = IntCollection(numPtr + 1, 2);
+  constexpr const auto numCollRange = range(numColl);
+  EXPECT_EQ(1, numCollRange[1]);
+  constexpr const auto numCollRangeSize = numCollRange.size();
+  EXPECT_EQ(2, numCollRangeSize);
+}
+
 std::string get_rand_str(size_t size,
                          std::uniform_int_distribution<>& dist,
                          std::mt19937& gen) {