00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "absl/container/internal/compressed_tuple.h"
00016
00017 #include <memory>
00018 #include <string>
00019
00020 #include "gmock/gmock.h"
00021 #include "gtest/gtest.h"
00022 #include "absl/memory/memory.h"
00023 #include "absl/utility/utility.h"
00024
00025 namespace absl {
00026 namespace container_internal {
00027 namespace {
00028
00029 enum class CallType { kConstRef, kConstMove };
00030
00031 template <int>
00032 struct Empty {
00033 constexpr CallType value() const& { return CallType::kConstRef; }
00034 constexpr CallType value() const&& { return CallType::kConstMove; }
00035 };
00036
00037 template <typename T>
00038 struct NotEmpty {
00039 T value;
00040 };
00041
00042 template <typename T, typename U>
00043 struct TwoValues {
00044 T value1;
00045 U value2;
00046 };
00047
00048 TEST(CompressedTupleTest, Sizeof) {
00049 EXPECT_EQ(sizeof(int), sizeof(CompressedTuple<int>));
00050 EXPECT_EQ(sizeof(int), sizeof(CompressedTuple<int, Empty<0>>));
00051 EXPECT_EQ(sizeof(int), sizeof(CompressedTuple<int, Empty<0>, Empty<1>>));
00052 EXPECT_EQ(sizeof(int),
00053 sizeof(CompressedTuple<int, Empty<0>, Empty<1>, Empty<2>>));
00054
00055 EXPECT_EQ(sizeof(TwoValues<int, double>),
00056 sizeof(CompressedTuple<int, NotEmpty<double>>));
00057 EXPECT_EQ(sizeof(TwoValues<int, double>),
00058 sizeof(CompressedTuple<int, Empty<0>, NotEmpty<double>>));
00059 EXPECT_EQ(sizeof(TwoValues<int, double>),
00060 sizeof(CompressedTuple<int, Empty<0>, NotEmpty<double>, Empty<1>>));
00061 }
00062
00063 TEST(CompressedTupleTest, Access) {
00064 struct S {
00065 std::string x;
00066 };
00067 CompressedTuple<int, Empty<0>, S> x(7, {}, S{"ABC"});
00068 EXPECT_EQ(sizeof(x), sizeof(TwoValues<int, S>));
00069 EXPECT_EQ(7, x.get<0>());
00070 EXPECT_EQ("ABC", x.get<2>().x);
00071 }
00072
00073 TEST(CompressedTupleTest, NonClasses) {
00074 CompressedTuple<int, const char*> x(7, "ABC");
00075 EXPECT_EQ(7, x.get<0>());
00076 EXPECT_STREQ("ABC", x.get<1>());
00077 }
00078
00079 TEST(CompressedTupleTest, MixClassAndNonClass) {
00080 CompressedTuple<int, const char*, Empty<0>, NotEmpty<double>> x(7, "ABC", {},
00081 {1.25});
00082 struct Mock {
00083 int v;
00084 const char* p;
00085 double d;
00086 };
00087 EXPECT_EQ(sizeof(x), sizeof(Mock));
00088 EXPECT_EQ(7, x.get<0>());
00089 EXPECT_STREQ("ABC", x.get<1>());
00090 EXPECT_EQ(1.25, x.get<3>().value);
00091 }
00092
00093 TEST(CompressedTupleTest, Nested) {
00094 CompressedTuple<int, CompressedTuple<int>,
00095 CompressedTuple<int, CompressedTuple<int>>>
00096 x(1, CompressedTuple<int>(2),
00097 CompressedTuple<int, CompressedTuple<int>>(3, CompressedTuple<int>(4)));
00098 EXPECT_EQ(1, x.get<0>());
00099 EXPECT_EQ(2, x.get<1>().get<0>());
00100 EXPECT_EQ(3, x.get<2>().get<0>());
00101 EXPECT_EQ(4, x.get<2>().get<1>().get<0>());
00102
00103 CompressedTuple<Empty<0>, Empty<0>,
00104 CompressedTuple<Empty<0>, CompressedTuple<Empty<0>>>>
00105 y;
00106 std::set<Empty<0>*> empties{&y.get<0>(), &y.get<1>(), &y.get<2>().get<0>(),
00107 &y.get<2>().get<1>().get<0>()};
00108 #ifdef _MSC_VER
00109
00110
00111
00112 int expected = 1;
00113 #else
00114 int expected = 4;
00115 #endif
00116 EXPECT_EQ(expected, sizeof(y));
00117 EXPECT_EQ(expected, empties.size());
00118 EXPECT_EQ(sizeof(y), sizeof(Empty<0>) * empties.size());
00119
00120 EXPECT_EQ(4 * sizeof(char),
00121 sizeof(CompressedTuple<CompressedTuple<char, char>,
00122 CompressedTuple<char, char>>));
00123 EXPECT_TRUE(
00124 (std::is_empty<CompressedTuple<CompressedTuple<Empty<0>>,
00125 CompressedTuple<Empty<1>>>>::value));
00126 }
00127
00128 TEST(CompressedTupleTest, Reference) {
00129 int i = 7;
00130 std::string s = "Very long std::string that goes in the heap";
00131 CompressedTuple<int, int&, std::string, std::string&> x(i, i, s, s);
00132
00133
00134 EXPECT_EQ(s, "Very long std::string that goes in the heap");
00135
00136 EXPECT_EQ(x.get<0>(), x.get<1>());
00137 EXPECT_NE(&x.get<0>(), &x.get<1>());
00138 EXPECT_EQ(&x.get<1>(), &i);
00139
00140 EXPECT_EQ(x.get<2>(), x.get<3>());
00141 EXPECT_NE(&x.get<2>(), &x.get<3>());
00142 EXPECT_EQ(&x.get<3>(), &s);
00143 }
00144
00145 TEST(CompressedTupleTest, NoElements) {
00146 CompressedTuple<> x;
00147 static_cast<void>(x);
00148 EXPECT_TRUE(std::is_empty<CompressedTuple<>>::value);
00149 }
00150
00151 TEST(CompressedTupleTest, MoveOnlyElements) {
00152 CompressedTuple<std::unique_ptr<std::string>> str_tup(
00153 absl::make_unique<std::string>("str"));
00154
00155 CompressedTuple<CompressedTuple<std::unique_ptr<std::string>>,
00156 std::unique_ptr<int>>
00157 x(std::move(str_tup), absl::make_unique<int>(5));
00158
00159 EXPECT_EQ(*x.get<0>().get<0>(), "str");
00160 EXPECT_EQ(*x.get<1>(), 5);
00161
00162 std::unique_ptr<std::string> x0 = std::move(x.get<0>()).get<0>();
00163 std::unique_ptr<int> x1 = std::move(x).get<1>();
00164
00165 EXPECT_EQ(*x0, "str");
00166 EXPECT_EQ(*x1, 5);
00167 }
00168
00169 TEST(CompressedTupleTest, Constexpr) {
00170 constexpr CompressedTuple<int, double, CompressedTuple<int>, Empty<0>> x(
00171 7, 1.25, CompressedTuple<int>(5), {});
00172 constexpr int x0 = x.get<0>();
00173 constexpr double x1 = x.get<1>();
00174 constexpr int x2 = x.get<2>().get<0>();
00175 constexpr CallType x3 = x.get<3>().value();
00176
00177 EXPECT_EQ(x0, 7);
00178 EXPECT_EQ(x1, 1.25);
00179 EXPECT_EQ(x2, 5);
00180 EXPECT_EQ(x3, CallType::kConstRef);
00181
00182 #if defined(__clang__)
00183
00184 constexpr int x2m = absl::move(x.get<2>()).get<0>();
00185 constexpr CallType x3m = absl::move(x).get<3>().value();
00186 EXPECT_EQ(x2m, 5);
00187 EXPECT_EQ(x3m, CallType::kConstMove);
00188 #endif
00189 }
00190
00191 #if defined(__clang__) || defined(__GNUC__)
00192 TEST(CompressedTupleTest, EmptyFinalClass) {
00193 struct S final {
00194 int f() const { return 5; }
00195 };
00196 CompressedTuple<S> x;
00197 EXPECT_EQ(x.get<0>().f(), 5);
00198 }
00199 #endif
00200
00201 }
00202 }
00203 }