compressed_tuple_test.cc
Go to the documentation of this file.
00001 // Copyright 2018 The Abseil Authors.
00002 //
00003 // Licensed under the Apache License, Version 2.0 (the "License");
00004 // you may not use this file except in compliance with the License.
00005 // You may obtain a copy of the License at
00006 //
00007 //      https://www.apache.org/licenses/LICENSE-2.0
00008 //
00009 // Unless required by applicable law or agreed to in writing, software
00010 // distributed under the License is distributed on an "AS IS" BASIS,
00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012 // See the License for the specific language governing permissions and
00013 // limitations under the License.
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   // MSVC has a bug where many instances of the same base class are layed out in
00110   // the same address when using __declspec(empty_bases).
00111   // This will be fixed in a future version of MSVC.
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   // Sanity check. We should have not moved from `s`
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);  // Silence -Wunused-variable.
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   // An apparent bug in earlier versions of gcc claims these are ambiguous.
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 }  // namespace
00202 }  // namespace container_internal
00203 }  // namespace absl


abseil_cpp
Author(s):
autogenerated on Wed Jun 19 2019 19:42:14