proxygen
TupleOpsTest.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2015-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
18 
19 #include <folly/Conv.h>
21 
22 #include <glog/logging.h>
23 
24 namespace folly {
25 namespace test {
26 
27 TEST(TupleOps, Copiable) {
28  auto t = std::make_tuple(10, std::string("hello"), 30);
29 
30  EXPECT_EQ(10, std::get<0>(t));
31  auto t1 = tupleRange<1>(t);
32  EXPECT_EQ("hello", std::get<0>(t1));
33  EXPECT_EQ(2, std::tuple_size<decltype(t1)>::value);
34  auto t2 = tupleRange<1, 1>(t);
35  EXPECT_EQ(1, std::tuple_size<decltype(t2)>::value);
36  EXPECT_EQ("hello", std::get<0>(t2));
37  EXPECT_EQ(30, std::get<0>(tupleRange<1>(tupleRange<1>(t))));
38 
39  EXPECT_TRUE(t == tuplePrepend(std::get<0>(t), tupleRange<1>(t)));
40 }
41 
42 class MovableInt {
43  public:
44  explicit MovableInt(int value) : value_(value) {}
45  int value() const {
46  return value_;
47  }
48 
49  MovableInt(MovableInt&&) = default;
50  MovableInt& operator=(MovableInt&&) = default;
51  MovableInt(const MovableInt&) = delete;
52  MovableInt& operator=(const MovableInt&) = delete;
53 
54  private:
55  int value_;
56 };
57 
58 bool operator==(const MovableInt& a, const MovableInt& b) {
59  return a.value() == b.value();
60 }
61 
62 TEST(TupleOps, Movable) {
63  auto t1 = std::make_tuple(MovableInt(10), std::string("hello"), 30);
64  auto t2 = std::make_tuple(MovableInt(10), std::string("hello"), 30);
65  auto t3 = std::make_tuple(MovableInt(10), std::string("hello"), 30);
66 
67  auto t1car = std::get<0>(std::move(t1));
68  auto t2cdr = tupleRange<1>(std::move(t2));
69 
70  EXPECT_TRUE(t3 == tuplePrepend(std::move(t1car), std::move(t2cdr)));
71 }
72 
73 // Given a tuple of As, convert to a tuple of Bs (of the same size)
74 // by calling folly::to on matching types.
75 //
76 // There are two example implementation: tupleTo (using tail recursion), which
77 // may create a lot of intermediate tuples, and tupleTo2, using
78 // TemplateTupleRange directly (below).
79 template <class U, class T>
80 U tupleTo(const T& input);
81 
82 template <class U, class T>
83 struct TupleTo;
84 
85 // Base case: empty typle -> empty tuple
86 template <>
87 struct TupleTo<std::tuple<>, std::tuple<>> {
88  static std::tuple<> convert(const std::tuple<>& /* input */) {
89  return std::make_tuple();
90  }
91 };
92 
93 // Induction case: split off head element and convert it, then call tupleTo on
94 // the tail.
95 template <class U, class... Us, class T>
96 struct TupleTo<std::tuple<U, Us...>, T> {
97  static std::tuple<U, Us...> convert(const T& input) {
98  return tuplePrepend(
99  folly::to<U>(std::get<0>(input)),
100  tupleTo<std::tuple<Us...>>(tupleRange<1>(input)));
101  }
102 };
103 
104 template <class U, class T>
105 U tupleTo(const T& input) {
106  return TupleTo<U, T>::convert(input);
107 }
108 
109 template <class S>
110 struct TupleTo2;
111 
112 // Destructure all indexes into Ns... and use parameter pack expansion
113 // to repeat the conversion for each individual element, then wrap
114 // all results with make_tuple.
115 template <std::size_t... Ns>
116 struct TupleTo2<TemplateSeq<std::size_t, Ns...>> {
117  template <class U, class T>
118  static U convert(const T& input) {
120  std::get<Ns>(input))...);
121  }
122 };
123 
124 template <
125  class U,
126  class T,
127  class Seq = typename TemplateTupleRange<U>::type,
128  class Enable = typename std::enable_if<
130 U tupleTo2(const T& input) {
131  return TupleTo2<Seq>::template convert<U>(input);
132 }
133 
134 #define CHECK_TUPLE_TO(converter) \
135  do { \
136  auto src = std::make_tuple(42, "50", 10); \
137  auto dest = converter<std::tuple<std::string, int, int>>(src); \
138  EXPECT_EQ("42", std::get<0>(dest)); \
139  EXPECT_EQ(50, std::get<1>(dest)); \
140  EXPECT_EQ(10, std::get<2>(dest)); \
141  } while (false)
142 
143 TEST(TupleOps, TupleTo) {
144  CHECK_TUPLE_TO(tupleTo);
145 }
146 
147 TEST(TupleOps, TupleTo2) {
149 }
150 
151 #undef CHECK_TUPLE_TO
152 
153 } // namespace test
154 } // namespace folly
U tupleTo2(const T &input)
char b
PskType type
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
static std::tuple convert(const std::tuple<> &)
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
STL namespace.
#define CHECK_TUPLE_TO(converter)
folly::std T
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
tuple make_tuple()
Definition: gtest-tuple.h:675
static std::tuple< U, Us... > convert(const T &input)
std::enable_if< detail::is_chrono_conversion< Tgt, Src >::value, Tgt >::type to(const Src &value)
Definition: Conv.h:677
U tupleTo(const T &input)
char a
static const char *const value
Definition: Conv.cpp:50
bool operator==(const MovableInt &a, const MovableInt &b)
auto tuplePrepend(T &&car, U &&cdr) -> decltype(std::tuple_cat(std::make_tuple(std::forward< T >(car)), std::forward< U >(cdr)))
Definition: TupleOps.h:117
TEST(ProgramOptionsTest, Errors)
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
const char * string
Definition: Conv.cpp:212
MovableInt & operator=(MovableInt &&)=default
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
typename TemplateRange< std::size_t, start,(n<=size-start?n:size-start)>::type type
Definition: TupleOps.h:78