layout_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/layout.h"
00016 
00017 // We need ::max_align_t because some libstdc++ versions don't provide
00018 // std::max_align_t
00019 #include <stddef.h>
00020 #include <cstdint>
00021 #include <memory>
00022 #include <sstream>
00023 #include <type_traits>
00024 
00025 #include "gmock/gmock.h"
00026 #include "gtest/gtest.h"
00027 #include "absl/base/internal/raw_logging.h"
00028 #include "absl/types/span.h"
00029 
00030 namespace absl {
00031 namespace container_internal {
00032 namespace {
00033 
00034 using ::absl::Span;
00035 using ::testing::ElementsAre;
00036 
00037 size_t Distance(const void* from, const void* to) {
00038   ABSL_RAW_CHECK(from <= to, "Distance must be non-negative");
00039   return static_cast<const char*>(to) - static_cast<const char*>(from);
00040 }
00041 
00042 template <class Expected, class Actual>
00043 Expected Type(Actual val) {
00044   static_assert(std::is_same<Expected, Actual>(), "");
00045   return val;
00046 }
00047 
00048 // Helper classes to test different size and alignments.
00049 struct alignas(8) Int128 {
00050   uint64_t a, b;
00051   friend bool operator==(Int128 lhs, Int128 rhs) {
00052     return std::tie(lhs.a, lhs.b) == std::tie(rhs.a, rhs.b);
00053   }
00054 
00055   static std::string Name() {
00056     return internal_layout::adl_barrier::TypeName<Int128>();
00057   }
00058 };
00059 
00060 // int64_t is *not* 8-byte aligned on all platforms!
00061 struct alignas(8) Int64 {
00062   int64_t a;
00063   friend bool operator==(Int64 lhs, Int64 rhs) {
00064     return lhs.a == rhs.a;
00065   }
00066 };
00067 
00068 // Properties of types that this test relies on.
00069 static_assert(sizeof(int8_t) == 1, "");
00070 static_assert(alignof(int8_t) == 1, "");
00071 static_assert(sizeof(int16_t) == 2, "");
00072 static_assert(alignof(int16_t) == 2, "");
00073 static_assert(sizeof(int32_t) == 4, "");
00074 static_assert(alignof(int32_t) == 4, "");
00075 static_assert(sizeof(Int64) == 8, "");
00076 static_assert(alignof(Int64) == 8, "");
00077 static_assert(sizeof(Int128) == 16, "");
00078 static_assert(alignof(Int128) == 8, "");
00079 
00080 template <class Expected, class Actual>
00081 void SameType() {
00082   static_assert(std::is_same<Expected, Actual>(), "");
00083 }
00084 
00085 TEST(Layout, ElementType) {
00086   {
00087     using L = Layout<int32_t>;
00088     SameType<int32_t, L::ElementType<0>>();
00089     SameType<int32_t, decltype(L::Partial())::ElementType<0>>();
00090     SameType<int32_t, decltype(L::Partial(0))::ElementType<0>>();
00091   }
00092   {
00093     using L = Layout<int32_t, int32_t>;
00094     SameType<int32_t, L::ElementType<0>>();
00095     SameType<int32_t, L::ElementType<1>>();
00096     SameType<int32_t, decltype(L::Partial())::ElementType<0>>();
00097     SameType<int32_t, decltype(L::Partial())::ElementType<1>>();
00098     SameType<int32_t, decltype(L::Partial(0))::ElementType<0>>();
00099     SameType<int32_t, decltype(L::Partial(0))::ElementType<1>>();
00100   }
00101   {
00102     using L = Layout<int8_t, int32_t, Int128>;
00103     SameType<int8_t, L::ElementType<0>>();
00104     SameType<int32_t, L::ElementType<1>>();
00105     SameType<Int128, L::ElementType<2>>();
00106     SameType<int8_t, decltype(L::Partial())::ElementType<0>>();
00107     SameType<int8_t, decltype(L::Partial(0))::ElementType<0>>();
00108     SameType<int32_t, decltype(L::Partial(0))::ElementType<1>>();
00109     SameType<int8_t, decltype(L::Partial(0, 0))::ElementType<0>>();
00110     SameType<int32_t, decltype(L::Partial(0, 0))::ElementType<1>>();
00111     SameType<Int128, decltype(L::Partial(0, 0))::ElementType<2>>();
00112     SameType<int8_t, decltype(L::Partial(0, 0, 0))::ElementType<0>>();
00113     SameType<int32_t, decltype(L::Partial(0, 0, 0))::ElementType<1>>();
00114     SameType<Int128, decltype(L::Partial(0, 0, 0))::ElementType<2>>();
00115   }
00116 }
00117 
00118 TEST(Layout, ElementTypes) {
00119   {
00120     using L = Layout<int32_t>;
00121     SameType<std::tuple<int32_t>, L::ElementTypes>();
00122     SameType<std::tuple<int32_t>, decltype(L::Partial())::ElementTypes>();
00123     SameType<std::tuple<int32_t>, decltype(L::Partial(0))::ElementTypes>();
00124   }
00125   {
00126     using L = Layout<int32_t, int32_t>;
00127     SameType<std::tuple<int32_t, int32_t>, L::ElementTypes>();
00128     SameType<std::tuple<int32_t, int32_t>, decltype(L::Partial())::ElementTypes>();
00129     SameType<std::tuple<int32_t, int32_t>, decltype(L::Partial(0))::ElementTypes>();
00130   }
00131   {
00132     using L = Layout<int8_t, int32_t, Int128>;
00133     SameType<std::tuple<int8_t, int32_t, Int128>, L::ElementTypes>();
00134     SameType<std::tuple<int8_t, int32_t, Int128>,
00135              decltype(L::Partial())::ElementTypes>();
00136     SameType<std::tuple<int8_t, int32_t, Int128>,
00137              decltype(L::Partial(0))::ElementTypes>();
00138     SameType<std::tuple<int8_t, int32_t, Int128>,
00139              decltype(L::Partial(0, 0))::ElementTypes>();
00140     SameType<std::tuple<int8_t, int32_t, Int128>,
00141              decltype(L::Partial(0, 0, 0))::ElementTypes>();
00142   }
00143 }
00144 
00145 TEST(Layout, OffsetByIndex) {
00146   {
00147     using L = Layout<int32_t>;
00148     EXPECT_EQ(0, L::Partial().Offset<0>());
00149     EXPECT_EQ(0, L::Partial(3).Offset<0>());
00150     EXPECT_EQ(0, L(3).Offset<0>());
00151   }
00152   {
00153     using L = Layout<int32_t, int32_t>;
00154     EXPECT_EQ(0, L::Partial().Offset<0>());
00155     EXPECT_EQ(0, L::Partial(3).Offset<0>());
00156     EXPECT_EQ(12, L::Partial(3).Offset<1>());
00157     EXPECT_EQ(0, L::Partial(3, 5).Offset<0>());
00158     EXPECT_EQ(12, L::Partial(3, 5).Offset<1>());
00159     EXPECT_EQ(0, L(3, 5).Offset<0>());
00160     EXPECT_EQ(12, L(3, 5).Offset<1>());
00161   }
00162   {
00163     using L = Layout<int8_t, int32_t, Int128>;
00164     EXPECT_EQ(0, L::Partial().Offset<0>());
00165     EXPECT_EQ(0, L::Partial(0).Offset<0>());
00166     EXPECT_EQ(0, L::Partial(0).Offset<1>());
00167     EXPECT_EQ(0, L::Partial(1).Offset<0>());
00168     EXPECT_EQ(4, L::Partial(1).Offset<1>());
00169     EXPECT_EQ(0, L::Partial(5).Offset<0>());
00170     EXPECT_EQ(8, L::Partial(5).Offset<1>());
00171     EXPECT_EQ(0, L::Partial(0, 0).Offset<0>());
00172     EXPECT_EQ(0, L::Partial(0, 0).Offset<1>());
00173     EXPECT_EQ(0, L::Partial(0, 0).Offset<2>());
00174     EXPECT_EQ(0, L::Partial(1, 0).Offset<0>());
00175     EXPECT_EQ(4, L::Partial(1, 0).Offset<1>());
00176     EXPECT_EQ(8, L::Partial(1, 0).Offset<2>());
00177     EXPECT_EQ(0, L::Partial(5, 3).Offset<0>());
00178     EXPECT_EQ(8, L::Partial(5, 3).Offset<1>());
00179     EXPECT_EQ(24, L::Partial(5, 3).Offset<2>());
00180     EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<0>());
00181     EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<1>());
00182     EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<2>());
00183     EXPECT_EQ(0, L::Partial(1, 0, 0).Offset<0>());
00184     EXPECT_EQ(4, L::Partial(1, 0, 0).Offset<1>());
00185     EXPECT_EQ(8, L::Partial(1, 0, 0).Offset<2>());
00186     EXPECT_EQ(0, L::Partial(5, 3, 1).Offset<0>());
00187     EXPECT_EQ(24, L::Partial(5, 3, 1).Offset<2>());
00188     EXPECT_EQ(8, L::Partial(5, 3, 1).Offset<1>());
00189     EXPECT_EQ(0, L(5, 3, 1).Offset<0>());
00190     EXPECT_EQ(24, L(5, 3, 1).Offset<2>());
00191     EXPECT_EQ(8, L(5, 3, 1).Offset<1>());
00192   }
00193 }
00194 
00195 TEST(Layout, OffsetByType) {
00196   {
00197     using L = Layout<int32_t>;
00198     EXPECT_EQ(0, L::Partial().Offset<int32_t>());
00199     EXPECT_EQ(0, L::Partial(3).Offset<int32_t>());
00200     EXPECT_EQ(0, L(3).Offset<int32_t>());
00201   }
00202   {
00203     using L = Layout<int8_t, int32_t, Int128>;
00204     EXPECT_EQ(0, L::Partial().Offset<int8_t>());
00205     EXPECT_EQ(0, L::Partial(0).Offset<int8_t>());
00206     EXPECT_EQ(0, L::Partial(0).Offset<int32_t>());
00207     EXPECT_EQ(0, L::Partial(1).Offset<int8_t>());
00208     EXPECT_EQ(4, L::Partial(1).Offset<int32_t>());
00209     EXPECT_EQ(0, L::Partial(5).Offset<int8_t>());
00210     EXPECT_EQ(8, L::Partial(5).Offset<int32_t>());
00211     EXPECT_EQ(0, L::Partial(0, 0).Offset<int8_t>());
00212     EXPECT_EQ(0, L::Partial(0, 0).Offset<int32_t>());
00213     EXPECT_EQ(0, L::Partial(0, 0).Offset<Int128>());
00214     EXPECT_EQ(0, L::Partial(1, 0).Offset<int8_t>());
00215     EXPECT_EQ(4, L::Partial(1, 0).Offset<int32_t>());
00216     EXPECT_EQ(8, L::Partial(1, 0).Offset<Int128>());
00217     EXPECT_EQ(0, L::Partial(5, 3).Offset<int8_t>());
00218     EXPECT_EQ(8, L::Partial(5, 3).Offset<int32_t>());
00219     EXPECT_EQ(24, L::Partial(5, 3).Offset<Int128>());
00220     EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<int8_t>());
00221     EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<int32_t>());
00222     EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<Int128>());
00223     EXPECT_EQ(0, L::Partial(1, 0, 0).Offset<int8_t>());
00224     EXPECT_EQ(4, L::Partial(1, 0, 0).Offset<int32_t>());
00225     EXPECT_EQ(8, L::Partial(1, 0, 0).Offset<Int128>());
00226     EXPECT_EQ(0, L::Partial(5, 3, 1).Offset<int8_t>());
00227     EXPECT_EQ(24, L::Partial(5, 3, 1).Offset<Int128>());
00228     EXPECT_EQ(8, L::Partial(5, 3, 1).Offset<int32_t>());
00229     EXPECT_EQ(0, L(5, 3, 1).Offset<int8_t>());
00230     EXPECT_EQ(24, L(5, 3, 1).Offset<Int128>());
00231     EXPECT_EQ(8, L(5, 3, 1).Offset<int32_t>());
00232   }
00233 }
00234 
00235 TEST(Layout, Offsets) {
00236   {
00237     using L = Layout<int32_t>;
00238     EXPECT_THAT(L::Partial().Offsets(), ElementsAre(0));
00239     EXPECT_THAT(L::Partial(3).Offsets(), ElementsAre(0));
00240     EXPECT_THAT(L(3).Offsets(), ElementsAre(0));
00241   }
00242   {
00243     using L = Layout<int32_t, int32_t>;
00244     EXPECT_THAT(L::Partial().Offsets(), ElementsAre(0));
00245     EXPECT_THAT(L::Partial(3).Offsets(), ElementsAre(0, 12));
00246     EXPECT_THAT(L::Partial(3, 5).Offsets(), ElementsAre(0, 12));
00247     EXPECT_THAT(L(3, 5).Offsets(), ElementsAre(0, 12));
00248   }
00249   {
00250     using L = Layout<int8_t, int32_t, Int128>;
00251     EXPECT_THAT(L::Partial().Offsets(), ElementsAre(0));
00252     EXPECT_THAT(L::Partial(1).Offsets(), ElementsAre(0, 4));
00253     EXPECT_THAT(L::Partial(5).Offsets(), ElementsAre(0, 8));
00254     EXPECT_THAT(L::Partial(0, 0).Offsets(), ElementsAre(0, 0, 0));
00255     EXPECT_THAT(L::Partial(1, 0).Offsets(), ElementsAre(0, 4, 8));
00256     EXPECT_THAT(L::Partial(5, 3).Offsets(), ElementsAre(0, 8, 24));
00257     EXPECT_THAT(L::Partial(0, 0, 0).Offsets(), ElementsAre(0, 0, 0));
00258     EXPECT_THAT(L::Partial(1, 0, 0).Offsets(), ElementsAre(0, 4, 8));
00259     EXPECT_THAT(L::Partial(5, 3, 1).Offsets(), ElementsAre(0, 8, 24));
00260     EXPECT_THAT(L(5, 3, 1).Offsets(), ElementsAre(0, 8, 24));
00261   }
00262 }
00263 
00264 TEST(Layout, AllocSize) {
00265   {
00266     using L = Layout<int32_t>;
00267     EXPECT_EQ(0, L::Partial(0).AllocSize());
00268     EXPECT_EQ(12, L::Partial(3).AllocSize());
00269     EXPECT_EQ(12, L(3).AllocSize());
00270   }
00271   {
00272     using L = Layout<int32_t, int32_t>;
00273     EXPECT_EQ(32, L::Partial(3, 5).AllocSize());
00274     EXPECT_EQ(32, L(3, 5).AllocSize());
00275   }
00276   {
00277     using L = Layout<int8_t, int32_t, Int128>;
00278     EXPECT_EQ(0, L::Partial(0, 0, 0).AllocSize());
00279     EXPECT_EQ(8, L::Partial(1, 0, 0).AllocSize());
00280     EXPECT_EQ(8, L::Partial(0, 1, 0).AllocSize());
00281     EXPECT_EQ(16, L::Partial(0, 0, 1).AllocSize());
00282     EXPECT_EQ(24, L::Partial(1, 1, 1).AllocSize());
00283     EXPECT_EQ(136, L::Partial(3, 5, 7).AllocSize());
00284     EXPECT_EQ(136, L(3, 5, 7).AllocSize());
00285   }
00286 }
00287 
00288 TEST(Layout, SizeByIndex) {
00289   {
00290     using L = Layout<int32_t>;
00291     EXPECT_EQ(0, L::Partial(0).Size<0>());
00292     EXPECT_EQ(3, L::Partial(3).Size<0>());
00293     EXPECT_EQ(3, L(3).Size<0>());
00294   }
00295   {
00296     using L = Layout<int32_t, int32_t>;
00297     EXPECT_EQ(0, L::Partial(0).Size<0>());
00298     EXPECT_EQ(3, L::Partial(3).Size<0>());
00299     EXPECT_EQ(3, L::Partial(3, 5).Size<0>());
00300     EXPECT_EQ(5, L::Partial(3, 5).Size<1>());
00301     EXPECT_EQ(3, L(3, 5).Size<0>());
00302     EXPECT_EQ(5, L(3, 5).Size<1>());
00303   }
00304   {
00305     using L = Layout<int8_t, int32_t, Int128>;
00306     EXPECT_EQ(3, L::Partial(3).Size<0>());
00307     EXPECT_EQ(3, L::Partial(3, 5).Size<0>());
00308     EXPECT_EQ(5, L::Partial(3, 5).Size<1>());
00309     EXPECT_EQ(3, L::Partial(3, 5, 7).Size<0>());
00310     EXPECT_EQ(5, L::Partial(3, 5, 7).Size<1>());
00311     EXPECT_EQ(7, L::Partial(3, 5, 7).Size<2>());
00312     EXPECT_EQ(3, L(3, 5, 7).Size<0>());
00313     EXPECT_EQ(5, L(3, 5, 7).Size<1>());
00314     EXPECT_EQ(7, L(3, 5, 7).Size<2>());
00315   }
00316 }
00317 
00318 TEST(Layout, SizeByType) {
00319   {
00320     using L = Layout<int32_t>;
00321     EXPECT_EQ(0, L::Partial(0).Size<int32_t>());
00322     EXPECT_EQ(3, L::Partial(3).Size<int32_t>());
00323     EXPECT_EQ(3, L(3).Size<int32_t>());
00324   }
00325   {
00326     using L = Layout<int8_t, int32_t, Int128>;
00327     EXPECT_EQ(3, L::Partial(3).Size<int8_t>());
00328     EXPECT_EQ(3, L::Partial(3, 5).Size<int8_t>());
00329     EXPECT_EQ(5, L::Partial(3, 5).Size<int32_t>());
00330     EXPECT_EQ(3, L::Partial(3, 5, 7).Size<int8_t>());
00331     EXPECT_EQ(5, L::Partial(3, 5, 7).Size<int32_t>());
00332     EXPECT_EQ(7, L::Partial(3, 5, 7).Size<Int128>());
00333     EXPECT_EQ(3, L(3, 5, 7).Size<int8_t>());
00334     EXPECT_EQ(5, L(3, 5, 7).Size<int32_t>());
00335     EXPECT_EQ(7, L(3, 5, 7).Size<Int128>());
00336   }
00337 }
00338 
00339 TEST(Layout, Sizes) {
00340   {
00341     using L = Layout<int32_t>;
00342     EXPECT_THAT(L::Partial().Sizes(), ElementsAre());
00343     EXPECT_THAT(L::Partial(3).Sizes(), ElementsAre(3));
00344     EXPECT_THAT(L(3).Sizes(), ElementsAre(3));
00345   }
00346   {
00347     using L = Layout<int32_t, int32_t>;
00348     EXPECT_THAT(L::Partial().Sizes(), ElementsAre());
00349     EXPECT_THAT(L::Partial(3).Sizes(), ElementsAre(3));
00350     EXPECT_THAT(L::Partial(3, 5).Sizes(), ElementsAre(3, 5));
00351     EXPECT_THAT(L(3, 5).Sizes(), ElementsAre(3, 5));
00352   }
00353   {
00354     using L = Layout<int8_t, int32_t, Int128>;
00355     EXPECT_THAT(L::Partial().Sizes(), ElementsAre());
00356     EXPECT_THAT(L::Partial(3).Sizes(), ElementsAre(3));
00357     EXPECT_THAT(L::Partial(3, 5).Sizes(), ElementsAre(3, 5));
00358     EXPECT_THAT(L::Partial(3, 5, 7).Sizes(), ElementsAre(3, 5, 7));
00359     EXPECT_THAT(L(3, 5, 7).Sizes(), ElementsAre(3, 5, 7));
00360   }
00361 }
00362 
00363 TEST(Layout, PointerByIndex) {
00364   alignas(max_align_t) const unsigned char p[100] = {};
00365   {
00366     using L = Layout<int32_t>;
00367     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<0>(p))));
00368     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
00369     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3).Pointer<0>(p))));
00370   }
00371   {
00372     using L = Layout<int32_t, int32_t>;
00373     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<0>(p))));
00374     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p))));
00375     EXPECT_EQ(12, Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<1>(p))));
00376     EXPECT_EQ(0,
00377               Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<0>(p))));
00378     EXPECT_EQ(12,
00379               Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<1>(p))));
00380     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3, 5).Pointer<0>(p))));
00381     EXPECT_EQ(12, Distance(p, Type<const int32_t*>(L(3, 5).Pointer<1>(p))));
00382   }
00383   {
00384     using L = Layout<int8_t, int32_t, Int128>;
00385     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<0>(p))));
00386     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<0>(p))));
00387     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<1>(p))));
00388     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<0>(p))));
00389     EXPECT_EQ(4, Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<1>(p))));
00390     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<0>(p))));
00391     EXPECT_EQ(8, Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<1>(p))));
00392     EXPECT_EQ(0,
00393               Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<0>(p))));
00394     EXPECT_EQ(0,
00395               Distance(p, Type<const int32_t*>(L::Partial(0, 0).Pointer<1>(p))));
00396     EXPECT_EQ(0,
00397               Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<2>(p))));
00398     EXPECT_EQ(0,
00399               Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<0>(p))));
00400     EXPECT_EQ(4,
00401               Distance(p, Type<const int32_t*>(L::Partial(1, 0).Pointer<1>(p))));
00402     EXPECT_EQ(8,
00403               Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<2>(p))));
00404     EXPECT_EQ(0,
00405               Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<0>(p))));
00406     EXPECT_EQ(8,
00407               Distance(p, Type<const int32_t*>(L::Partial(5, 3).Pointer<1>(p))));
00408     EXPECT_EQ(24,
00409               Distance(p, Type<const Int128*>(L::Partial(5, 3).Pointer<2>(p))));
00410     EXPECT_EQ(
00411         0, Distance(p, Type<const int8_t*>(L::Partial(0, 0, 0).Pointer<0>(p))));
00412     EXPECT_EQ(
00413         0, Distance(p, Type<const int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
00414     EXPECT_EQ(
00415         0, Distance(p, Type<const Int128*>(L::Partial(0, 0, 0).Pointer<2>(p))));
00416     EXPECT_EQ(
00417         0, Distance(p, Type<const int8_t*>(L::Partial(1, 0, 0).Pointer<0>(p))));
00418     EXPECT_EQ(
00419         4, Distance(p, Type<const int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
00420     EXPECT_EQ(
00421         8, Distance(p, Type<const Int128*>(L::Partial(1, 0, 0).Pointer<2>(p))));
00422     EXPECT_EQ(
00423         0, Distance(p, Type<const int8_t*>(L::Partial(5, 3, 1).Pointer<0>(p))));
00424     EXPECT_EQ(
00425         24,
00426         Distance(p, Type<const Int128*>(L::Partial(5, 3, 1).Pointer<2>(p))));
00427     EXPECT_EQ(
00428         8, Distance(p, Type<const int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
00429     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L(5, 3, 1).Pointer<0>(p))));
00430     EXPECT_EQ(24, Distance(p, Type<const Int128*>(L(5, 3, 1).Pointer<2>(p))));
00431     EXPECT_EQ(8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<1>(p))));
00432   }
00433 }
00434 
00435 TEST(Layout, PointerByType) {
00436   alignas(max_align_t) const unsigned char p[100] = {};
00437   {
00438     using L = Layout<int32_t>;
00439     EXPECT_EQ(0,
00440               Distance(p, Type<const int32_t*>(L::Partial().Pointer<int32_t>(p))));
00441     EXPECT_EQ(0,
00442               Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
00443     EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3).Pointer<int32_t>(p))));
00444   }
00445   {
00446     using L = Layout<int8_t, int32_t, Int128>;
00447     EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<int8_t>(p))));
00448     EXPECT_EQ(0,
00449               Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<int8_t>(p))));
00450     EXPECT_EQ(0,
00451               Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
00452     EXPECT_EQ(0,
00453               Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<int8_t>(p))));
00454     EXPECT_EQ(4,
00455               Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
00456     EXPECT_EQ(0,
00457               Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<int8_t>(p))));
00458     EXPECT_EQ(8,
00459               Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
00460     EXPECT_EQ(
00461         0, Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
00462     EXPECT_EQ(
00463         0, Distance(p, Type<const int32_t*>(L::Partial(0, 0).Pointer<int32_t>(p))));
00464     EXPECT_EQ(
00465         0,
00466         Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<Int128>(p))));
00467     EXPECT_EQ(
00468         0, Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
00469     EXPECT_EQ(
00470         4, Distance(p, Type<const int32_t*>(L::Partial(1, 0).Pointer<int32_t>(p))));
00471     EXPECT_EQ(
00472         8,
00473         Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<Int128>(p))));
00474     EXPECT_EQ(
00475         0, Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
00476     EXPECT_EQ(
00477         8, Distance(p, Type<const int32_t*>(L::Partial(5, 3).Pointer<int32_t>(p))));
00478     EXPECT_EQ(
00479         24,
00480         Distance(p, Type<const Int128*>(L::Partial(5, 3).Pointer<Int128>(p))));
00481     EXPECT_EQ(
00482         0,
00483         Distance(p, Type<const int8_t*>(L::Partial(0, 0, 0).Pointer<int8_t>(p))));
00484     EXPECT_EQ(
00485         0,
00486         Distance(p, Type<const int32_t*>(L::Partial(0, 0, 0).Pointer<int32_t>(p))));
00487     EXPECT_EQ(0, Distance(p, Type<const Int128*>(
00488                                  L::Partial(0, 0, 0).Pointer<Int128>(p))));
00489     EXPECT_EQ(
00490         0,
00491         Distance(p, Type<const int8_t*>(L::Partial(1, 0, 0).Pointer<int8_t>(p))));
00492     EXPECT_EQ(
00493         4,
00494         Distance(p, Type<const int32_t*>(L::Partial(1, 0, 0).Pointer<int32_t>(p))));
00495     EXPECT_EQ(8, Distance(p, Type<const Int128*>(
00496                                  L::Partial(1, 0, 0).Pointer<Int128>(p))));
00497     EXPECT_EQ(
00498         0,
00499         Distance(p, Type<const int8_t*>(L::Partial(5, 3, 1).Pointer<int8_t>(p))));
00500     EXPECT_EQ(24, Distance(p, Type<const Int128*>(
00501                                   L::Partial(5, 3, 1).Pointer<Int128>(p))));
00502     EXPECT_EQ(
00503         8,
00504         Distance(p, Type<const int32_t*>(L::Partial(5, 3, 1).Pointer<int32_t>(p))));
00505     EXPECT_EQ(24,
00506               Distance(p, Type<const Int128*>(L(5, 3, 1).Pointer<Int128>(p))));
00507     EXPECT_EQ(8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<int32_t>(p))));
00508   }
00509 }
00510 
00511 TEST(Layout, MutablePointerByIndex) {
00512   alignas(max_align_t) unsigned char p[100];
00513   {
00514     using L = Layout<int32_t>;
00515     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<0>(p))));
00516     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<0>(p))));
00517     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3).Pointer<0>(p))));
00518   }
00519   {
00520     using L = Layout<int32_t, int32_t>;
00521     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<0>(p))));
00522     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<0>(p))));
00523     EXPECT_EQ(12, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<1>(p))));
00524     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3, 5).Pointer<0>(p))));
00525     EXPECT_EQ(12, Distance(p, Type<int32_t*>(L::Partial(3, 5).Pointer<1>(p))));
00526     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3, 5).Pointer<0>(p))));
00527     EXPECT_EQ(12, Distance(p, Type<int32_t*>(L(3, 5).Pointer<1>(p))));
00528   }
00529   {
00530     using L = Layout<int8_t, int32_t, Int128>;
00531     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial().Pointer<0>(p))));
00532     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0).Pointer<0>(p))));
00533     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0).Pointer<1>(p))));
00534     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1).Pointer<0>(p))));
00535     EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1).Pointer<1>(p))));
00536     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5).Pointer<0>(p))));
00537     EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5).Pointer<1>(p))));
00538     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0, 0).Pointer<0>(p))));
00539     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0, 0).Pointer<1>(p))));
00540     EXPECT_EQ(0, Distance(p, Type<Int128*>(L::Partial(0, 0).Pointer<2>(p))));
00541     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1, 0).Pointer<0>(p))));
00542     EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1, 0).Pointer<1>(p))));
00543     EXPECT_EQ(8, Distance(p, Type<Int128*>(L::Partial(1, 0).Pointer<2>(p))));
00544     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5, 3).Pointer<0>(p))));
00545     EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<1>(p))));
00546     EXPECT_EQ(24, Distance(p, Type<Int128*>(L::Partial(5, 3).Pointer<2>(p))));
00547     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<0>(p))));
00548     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p))));
00549     EXPECT_EQ(0, Distance(p, Type<Int128*>(L::Partial(0, 0, 0).Pointer<2>(p))));
00550     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<0>(p))));
00551     EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p))));
00552     EXPECT_EQ(8, Distance(p, Type<Int128*>(L::Partial(1, 0, 0).Pointer<2>(p))));
00553     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<0>(p))));
00554     EXPECT_EQ(24,
00555               Distance(p, Type<Int128*>(L::Partial(5, 3, 1).Pointer<2>(p))));
00556     EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p))));
00557     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L(5, 3, 1).Pointer<0>(p))));
00558     EXPECT_EQ(24, Distance(p, Type<Int128*>(L(5, 3, 1).Pointer<2>(p))));
00559     EXPECT_EQ(8, Distance(p, Type<int32_t*>(L(5, 3, 1).Pointer<1>(p))));
00560   }
00561 }
00562 
00563 TEST(Layout, MutablePointerByType) {
00564   alignas(max_align_t) unsigned char p[100];
00565   {
00566     using L = Layout<int32_t>;
00567     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<int32_t>(p))));
00568     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<int32_t>(p))));
00569     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3).Pointer<int32_t>(p))));
00570   }
00571   {
00572     using L = Layout<int8_t, int32_t, Int128>;
00573     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial().Pointer<int8_t>(p))));
00574     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0).Pointer<int8_t>(p))));
00575     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0).Pointer<int32_t>(p))));
00576     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1).Pointer<int8_t>(p))));
00577     EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1).Pointer<int32_t>(p))));
00578     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5).Pointer<int8_t>(p))));
00579     EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5).Pointer<int32_t>(p))));
00580     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p))));
00581     EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0, 0).Pointer<int32_t>(p))));
00582     EXPECT_EQ(0,
00583               Distance(p, Type<Int128*>(L::Partial(0, 0).Pointer<Int128>(p))));
00584     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p))));
00585     EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1, 0).Pointer<int32_t>(p))));
00586     EXPECT_EQ(8,
00587               Distance(p, Type<Int128*>(L::Partial(1, 0).Pointer<Int128>(p))));
00588     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p))));
00589     EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<int32_t>(p))));
00590     EXPECT_EQ(24,
00591               Distance(p, Type<Int128*>(L::Partial(5, 3).Pointer<Int128>(p))));
00592     EXPECT_EQ(0,
00593               Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<int8_t>(p))));
00594     EXPECT_EQ(0,
00595               Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<int32_t>(p))));
00596     EXPECT_EQ(
00597         0, Distance(p, Type<Int128*>(L::Partial(0, 0, 0).Pointer<Int128>(p))));
00598     EXPECT_EQ(0,
00599               Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<int8_t>(p))));
00600     EXPECT_EQ(4,
00601               Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<int32_t>(p))));
00602     EXPECT_EQ(
00603         8, Distance(p, Type<Int128*>(L::Partial(1, 0, 0).Pointer<Int128>(p))));
00604     EXPECT_EQ(0,
00605               Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<int8_t>(p))));
00606     EXPECT_EQ(
00607         24, Distance(p, Type<Int128*>(L::Partial(5, 3, 1).Pointer<Int128>(p))));
00608     EXPECT_EQ(8,
00609               Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<int32_t>(p))));
00610     EXPECT_EQ(0, Distance(p, Type<int8_t*>(L(5, 3, 1).Pointer<int8_t>(p))));
00611     EXPECT_EQ(24, Distance(p, Type<Int128*>(L(5, 3, 1).Pointer<Int128>(p))));
00612     EXPECT_EQ(8, Distance(p, Type<int32_t*>(L(5, 3, 1).Pointer<int32_t>(p))));
00613   }
00614 }
00615 
00616 TEST(Layout, Pointers) {
00617   alignas(max_align_t) const unsigned char p[100] = {};
00618   using L = Layout<int8_t, int8_t, Int128>;
00619   {
00620     const auto x = L::Partial();
00621     EXPECT_EQ(std::make_tuple(x.Pointer<0>(p)),
00622               Type<std::tuple<const int8_t*>>(x.Pointers(p)));
00623   }
00624   {
00625     const auto x = L::Partial(1);
00626     EXPECT_EQ(std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p)),
00627               (Type<std::tuple<const int8_t*, const int8_t*>>(x.Pointers(p))));
00628   }
00629   {
00630     const auto x = L::Partial(1, 2);
00631     EXPECT_EQ(
00632         std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
00633         (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
00634             x.Pointers(p))));
00635   }
00636   {
00637     const auto x = L::Partial(1, 2, 3);
00638     EXPECT_EQ(
00639         std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
00640         (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
00641             x.Pointers(p))));
00642   }
00643   {
00644     const L x(1, 2, 3);
00645     EXPECT_EQ(
00646         std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
00647         (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>(
00648             x.Pointers(p))));
00649   }
00650 }
00651 
00652 TEST(Layout, MutablePointers) {
00653   alignas(max_align_t) unsigned char p[100];
00654   using L = Layout<int8_t, int8_t, Int128>;
00655   {
00656     const auto x = L::Partial();
00657     EXPECT_EQ(std::make_tuple(x.Pointer<0>(p)),
00658               Type<std::tuple<int8_t*>>(x.Pointers(p)));
00659   }
00660   {
00661     const auto x = L::Partial(1);
00662     EXPECT_EQ(std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p)),
00663               (Type<std::tuple<int8_t*, int8_t*>>(x.Pointers(p))));
00664   }
00665   {
00666     const auto x = L::Partial(1, 2);
00667     EXPECT_EQ(
00668         std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
00669         (Type<std::tuple<int8_t*, int8_t*, Int128*>>(x.Pointers(p))));
00670   }
00671   {
00672     const auto x = L::Partial(1, 2, 3);
00673     EXPECT_EQ(
00674         std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
00675         (Type<std::tuple<int8_t*, int8_t*, Int128*>>(x.Pointers(p))));
00676   }
00677   {
00678     const L x(1, 2, 3);
00679     EXPECT_EQ(
00680         std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)),
00681         (Type<std::tuple<int8_t*, int8_t*, Int128*>>(x.Pointers(p))));
00682   }
00683 }
00684 
00685 TEST(Layout, SliceByIndexSize) {
00686   alignas(max_align_t) const unsigned char p[100] = {};
00687   {
00688     using L = Layout<int32_t>;
00689     EXPECT_EQ(0, L::Partial(0).Slice<0>(p).size());
00690     EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
00691     EXPECT_EQ(3, L(3).Slice<0>(p).size());
00692   }
00693   {
00694     using L = Layout<int32_t, int32_t>;
00695     EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
00696     EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());
00697     EXPECT_EQ(5, L(3, 5).Slice<1>(p).size());
00698   }
00699   {
00700     using L = Layout<int8_t, int32_t, Int128>;
00701     EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
00702     EXPECT_EQ(3, L::Partial(3, 5).Slice<0>(p).size());
00703     EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());
00704     EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<0>(p).size());
00705     EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<1>(p).size());
00706     EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<2>(p).size());
00707     EXPECT_EQ(3, L(3, 5, 7).Slice<0>(p).size());
00708     EXPECT_EQ(5, L(3, 5, 7).Slice<1>(p).size());
00709     EXPECT_EQ(7, L(3, 5, 7).Slice<2>(p).size());
00710   }
00711 }
00712 
00713 TEST(Layout, SliceByTypeSize) {
00714   alignas(max_align_t) const unsigned char p[100] = {};
00715   {
00716     using L = Layout<int32_t>;
00717     EXPECT_EQ(0, L::Partial(0).Slice<int32_t>(p).size());
00718     EXPECT_EQ(3, L::Partial(3).Slice<int32_t>(p).size());
00719     EXPECT_EQ(3, L(3).Slice<int32_t>(p).size());
00720   }
00721   {
00722     using L = Layout<int8_t, int32_t, Int128>;
00723     EXPECT_EQ(3, L::Partial(3).Slice<int8_t>(p).size());
00724     EXPECT_EQ(3, L::Partial(3, 5).Slice<int8_t>(p).size());
00725     EXPECT_EQ(5, L::Partial(3, 5).Slice<int32_t>(p).size());
00726     EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<int8_t>(p).size());
00727     EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<int32_t>(p).size());
00728     EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<Int128>(p).size());
00729     EXPECT_EQ(3, L(3, 5, 7).Slice<int8_t>(p).size());
00730     EXPECT_EQ(5, L(3, 5, 7).Slice<int32_t>(p).size());
00731     EXPECT_EQ(7, L(3, 5, 7).Slice<Int128>(p).size());
00732   }
00733 }
00734 
00735 TEST(Layout, MutableSliceByIndexSize) {
00736   alignas(max_align_t) unsigned char p[100];
00737   {
00738     using L = Layout<int32_t>;
00739     EXPECT_EQ(0, L::Partial(0).Slice<0>(p).size());
00740     EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
00741     EXPECT_EQ(3, L(3).Slice<0>(p).size());
00742   }
00743   {
00744     using L = Layout<int32_t, int32_t>;
00745     EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
00746     EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());
00747     EXPECT_EQ(5, L(3, 5).Slice<1>(p).size());
00748   }
00749   {
00750     using L = Layout<int8_t, int32_t, Int128>;
00751     EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size());
00752     EXPECT_EQ(3, L::Partial(3, 5).Slice<0>(p).size());
00753     EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size());
00754     EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<0>(p).size());
00755     EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<1>(p).size());
00756     EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<2>(p).size());
00757     EXPECT_EQ(3, L(3, 5, 7).Slice<0>(p).size());
00758     EXPECT_EQ(5, L(3, 5, 7).Slice<1>(p).size());
00759     EXPECT_EQ(7, L(3, 5, 7).Slice<2>(p).size());
00760   }
00761 }
00762 
00763 TEST(Layout, MutableSliceByTypeSize) {
00764   alignas(max_align_t) unsigned char p[100];
00765   {
00766     using L = Layout<int32_t>;
00767     EXPECT_EQ(0, L::Partial(0).Slice<int32_t>(p).size());
00768     EXPECT_EQ(3, L::Partial(3).Slice<int32_t>(p).size());
00769     EXPECT_EQ(3, L(3).Slice<int32_t>(p).size());
00770   }
00771   {
00772     using L = Layout<int8_t, int32_t, Int128>;
00773     EXPECT_EQ(3, L::Partial(3).Slice<int8_t>(p).size());
00774     EXPECT_EQ(3, L::Partial(3, 5).Slice<int8_t>(p).size());
00775     EXPECT_EQ(5, L::Partial(3, 5).Slice<int32_t>(p).size());
00776     EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<int8_t>(p).size());
00777     EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<int32_t>(p).size());
00778     EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<Int128>(p).size());
00779     EXPECT_EQ(3, L(3, 5, 7).Slice<int8_t>(p).size());
00780     EXPECT_EQ(5, L(3, 5, 7).Slice<int32_t>(p).size());
00781     EXPECT_EQ(7, L(3, 5, 7).Slice<Int128>(p).size());
00782   }
00783 }
00784 
00785 TEST(Layout, SliceByIndexData) {
00786   alignas(max_align_t) const unsigned char p[100] = {};
00787   {
00788     using L = Layout<int32_t>;
00789     EXPECT_EQ(
00790         0,
00791         Distance(p, Type<Span<const int32_t>>(L::Partial(0).Slice<0>(p)).data()));
00792     EXPECT_EQ(
00793         0,
00794         Distance(p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
00795     EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>(L(3).Slice<0>(p)).data()));
00796   }
00797   {
00798     using L = Layout<int32_t, int32_t>;
00799     EXPECT_EQ(
00800         0,
00801         Distance(p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data()));
00802     EXPECT_EQ(
00803         0,
00804         Distance(p,
00805                  Type<Span<const int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
00806     EXPECT_EQ(
00807         12,
00808         Distance(p,
00809                  Type<Span<const int32_t>>(L::Partial(3, 5).Slice<1>(p)).data()));
00810     EXPECT_EQ(0,
00811               Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<0>(p)).data()));
00812     EXPECT_EQ(12,
00813               Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<1>(p)).data()));
00814   }
00815   {
00816     using L = Layout<int8_t, int32_t, Int128>;
00817     EXPECT_EQ(
00818         0,
00819         Distance(p, Type<Span<const int8_t>>(L::Partial(0).Slice<0>(p)).data()));
00820     EXPECT_EQ(
00821         0,
00822         Distance(p, Type<Span<const int8_t>>(L::Partial(1).Slice<0>(p)).data()));
00823     EXPECT_EQ(
00824         0,
00825         Distance(p, Type<Span<const int8_t>>(L::Partial(5).Slice<0>(p)).data()));
00826     EXPECT_EQ(
00827         0, Distance(
00828                p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
00829     EXPECT_EQ(
00830         0,
00831         Distance(p,
00832                  Type<Span<const int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
00833     EXPECT_EQ(
00834         0, Distance(
00835                p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
00836     EXPECT_EQ(
00837         4,
00838         Distance(p,
00839                  Type<Span<const int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
00840     EXPECT_EQ(
00841         0, Distance(
00842                p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
00843     EXPECT_EQ(
00844         8,
00845         Distance(p,
00846                  Type<Span<const int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
00847     EXPECT_EQ(
00848         0,
00849         Distance(
00850             p, Type<Span<const int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
00851     EXPECT_EQ(
00852         0,
00853         Distance(
00854             p,
00855             Type<Span<const int32_t>>(L::Partial(0, 0, 0).Slice<1>(p)).data()));
00856     EXPECT_EQ(
00857         0,
00858         Distance(
00859             p,
00860             Type<Span<const Int128>>(L::Partial(0, 0, 0).Slice<2>(p)).data()));
00861     EXPECT_EQ(
00862         0,
00863         Distance(
00864             p, Type<Span<const int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
00865     EXPECT_EQ(
00866         4,
00867         Distance(
00868             p,
00869             Type<Span<const int32_t>>(L::Partial(1, 0, 0).Slice<1>(p)).data()));
00870     EXPECT_EQ(
00871         8,
00872         Distance(
00873             p,
00874             Type<Span<const Int128>>(L::Partial(1, 0, 0).Slice<2>(p)).data()));
00875     EXPECT_EQ(
00876         0,
00877         Distance(
00878             p, Type<Span<const int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
00879     EXPECT_EQ(
00880         24,
00881         Distance(
00882             p,
00883             Type<Span<const Int128>>(L::Partial(5, 3, 1).Slice<2>(p)).data()));
00884     EXPECT_EQ(
00885         8,
00886         Distance(
00887             p,
00888             Type<Span<const int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data()));
00889     EXPECT_EQ(
00890         0, Distance(p, Type<Span<const int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
00891     EXPECT_EQ(
00892         24,
00893         Distance(p, Type<Span<const Int128>>(L(5, 3, 1).Slice<2>(p)).data()));
00894     EXPECT_EQ(
00895         8, Distance(p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
00896   }
00897 }
00898 
00899 TEST(Layout, SliceByTypeData) {
00900   alignas(max_align_t) const unsigned char p[100] = {};
00901   {
00902     using L = Layout<int32_t>;
00903     EXPECT_EQ(
00904         0,
00905         Distance(
00906             p, Type<Span<const int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
00907     EXPECT_EQ(
00908         0,
00909         Distance(
00910             p, Type<Span<const int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
00911     EXPECT_EQ(
00912         0, Distance(p, Type<Span<const int32_t>>(L(3).Slice<int32_t>(p)).data()));
00913   }
00914   {
00915     using L = Layout<int8_t, int32_t, Int128>;
00916     EXPECT_EQ(
00917         0, Distance(
00918                p, Type<Span<const int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
00919     EXPECT_EQ(
00920         0, Distance(
00921                p, Type<Span<const int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
00922     EXPECT_EQ(
00923         0, Distance(
00924                p, Type<Span<const int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
00925     EXPECT_EQ(
00926         0,
00927         Distance(
00928             p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<int8_t>(p)).data()));
00929     EXPECT_EQ(
00930         0,
00931         Distance(
00932             p,
00933             Type<Span<const int32_t>>(L::Partial(0, 0).Slice<int32_t>(p)).data()));
00934     EXPECT_EQ(
00935         0,
00936         Distance(
00937             p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<int8_t>(p)).data()));
00938     EXPECT_EQ(
00939         4,
00940         Distance(
00941             p,
00942             Type<Span<const int32_t>>(L::Partial(1, 0).Slice<int32_t>(p)).data()));
00943     EXPECT_EQ(
00944         0,
00945         Distance(
00946             p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<int8_t>(p)).data()));
00947     EXPECT_EQ(
00948         8,
00949         Distance(
00950             p,
00951             Type<Span<const int32_t>>(L::Partial(5, 3).Slice<int32_t>(p)).data()));
00952     EXPECT_EQ(
00953         0,
00954         Distance(
00955             p,
00956             Type<Span<const int8_t>>(L::Partial(0, 0, 0).Slice<int8_t>(p)).data()));
00957     EXPECT_EQ(
00958         0,
00959         Distance(p, Type<Span<const int32_t>>(L::Partial(0, 0, 0).Slice<int32_t>(p))
00960                         .data()));
00961     EXPECT_EQ(0, Distance(p, Type<Span<const Int128>>(
00962                                  L::Partial(0, 0, 0).Slice<Int128>(p))
00963                                  .data()));
00964     EXPECT_EQ(
00965         0,
00966         Distance(
00967             p,
00968             Type<Span<const int8_t>>(L::Partial(1, 0, 0).Slice<int8_t>(p)).data()));
00969     EXPECT_EQ(
00970         4,
00971         Distance(p, Type<Span<const int32_t>>(L::Partial(1, 0, 0).Slice<int32_t>(p))
00972                         .data()));
00973     EXPECT_EQ(8, Distance(p, Type<Span<const Int128>>(
00974                                  L::Partial(1, 0, 0).Slice<Int128>(p))
00975                                  .data()));
00976     EXPECT_EQ(
00977         0,
00978         Distance(
00979             p,
00980             Type<Span<const int8_t>>(L::Partial(5, 3, 1).Slice<int8_t>(p)).data()));
00981     EXPECT_EQ(24, Distance(p, Type<Span<const Int128>>(
00982                                   L::Partial(5, 3, 1).Slice<Int128>(p))
00983                                   .data()));
00984     EXPECT_EQ(
00985         8,
00986         Distance(p, Type<Span<const int32_t>>(L::Partial(5, 3, 1).Slice<int32_t>(p))
00987                         .data()));
00988     EXPECT_EQ(
00989         0,
00990         Distance(p, Type<Span<const int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
00991     EXPECT_EQ(
00992         24,
00993         Distance(p,
00994                  Type<Span<const Int128>>(L(5, 3, 1).Slice<Int128>(p)).data()));
00995     EXPECT_EQ(
00996         8, Distance(
00997                p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
00998   }
00999 }
01000 
01001 TEST(Layout, MutableSliceByIndexData) {
01002   alignas(max_align_t) unsigned char p[100];
01003   {
01004     using L = Layout<int32_t>;
01005     EXPECT_EQ(0,
01006               Distance(p, Type<Span<int32_t>>(L::Partial(0).Slice<0>(p)).data()));
01007     EXPECT_EQ(0,
01008               Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
01009     EXPECT_EQ(0, Distance(p, Type<Span<int32_t>>(L(3).Slice<0>(p)).data()));
01010   }
01011   {
01012     using L = Layout<int32_t, int32_t>;
01013     EXPECT_EQ(0,
01014               Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data()));
01015     EXPECT_EQ(
01016         0, Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<0>(p)).data()));
01017     EXPECT_EQ(
01018         12,
01019         Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<1>(p)).data()));
01020     EXPECT_EQ(0, Distance(p, Type<Span<int32_t>>(L(3, 5).Slice<0>(p)).data()));
01021     EXPECT_EQ(12, Distance(p, Type<Span<int32_t>>(L(3, 5).Slice<1>(p)).data()));
01022   }
01023   {
01024     using L = Layout<int8_t, int32_t, Int128>;
01025     EXPECT_EQ(0,
01026               Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<0>(p)).data()));
01027     EXPECT_EQ(0,
01028               Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<0>(p)).data()));
01029     EXPECT_EQ(0,
01030               Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<0>(p)).data()));
01031     EXPECT_EQ(
01032         0, Distance(p, Type<Span<int8_t>>(L::Partial(0, 0).Slice<0>(p)).data()));
01033     EXPECT_EQ(
01034         0, Distance(p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<1>(p)).data()));
01035     EXPECT_EQ(
01036         0, Distance(p, Type<Span<int8_t>>(L::Partial(1, 0).Slice<0>(p)).data()));
01037     EXPECT_EQ(
01038         4, Distance(p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<1>(p)).data()));
01039     EXPECT_EQ(
01040         0, Distance(p, Type<Span<int8_t>>(L::Partial(5, 3).Slice<0>(p)).data()));
01041     EXPECT_EQ(
01042         8, Distance(p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<1>(p)).data()));
01043     EXPECT_EQ(
01044         0,
01045         Distance(p, Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data()));
01046     EXPECT_EQ(
01047         0,
01048         Distance(p, Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<1>(p)).data()));
01049     EXPECT_EQ(
01050         0, Distance(
01051                p, Type<Span<Int128>>(L::Partial(0, 0, 0).Slice<2>(p)).data()));
01052     EXPECT_EQ(
01053         0,
01054         Distance(p, Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data()));
01055     EXPECT_EQ(
01056         4,
01057         Distance(p, Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<1>(p)).data()));
01058     EXPECT_EQ(
01059         8, Distance(
01060                p, Type<Span<Int128>>(L::Partial(1, 0, 0).Slice<2>(p)).data()));
01061     EXPECT_EQ(
01062         0,
01063         Distance(p, Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data()));
01064     EXPECT_EQ(
01065         24, Distance(
01066                 p, Type<Span<Int128>>(L::Partial(5, 3, 1).Slice<2>(p)).data()));
01067     EXPECT_EQ(
01068         8,
01069         Distance(p, Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data()));
01070     EXPECT_EQ(0, Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<0>(p)).data()));
01071     EXPECT_EQ(24,
01072               Distance(p, Type<Span<Int128>>(L(5, 3, 1).Slice<2>(p)).data()));
01073     EXPECT_EQ(8, Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<1>(p)).data()));
01074   }
01075 }
01076 
01077 TEST(Layout, MutableSliceByTypeData) {
01078   alignas(max_align_t) unsigned char p[100];
01079   {
01080     using L = Layout<int32_t>;
01081     EXPECT_EQ(
01082         0,
01083         Distance(p, Type<Span<int32_t>>(L::Partial(0).Slice<int32_t>(p)).data()));
01084     EXPECT_EQ(
01085         0,
01086         Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<int32_t>(p)).data()));
01087     EXPECT_EQ(0, Distance(p, Type<Span<int32_t>>(L(3).Slice<int32_t>(p)).data()));
01088   }
01089   {
01090     using L = Layout<int8_t, int32_t, Int128>;
01091     EXPECT_EQ(
01092         0, Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<int8_t>(p)).data()));
01093     EXPECT_EQ(
01094         0, Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<int8_t>(p)).data()));
01095     EXPECT_EQ(
01096         0, Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<int8_t>(p)).data()));
01097     EXPECT_EQ(
01098         0,
01099         Distance(p, Type<Span<int8_t>>(L::Partial(0, 0).Slice<int8_t>(p)).data()));
01100     EXPECT_EQ(
01101         0, Distance(
01102                p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<int32_t>(p)).data()));
01103     EXPECT_EQ(
01104         0,
01105         Distance(p, Type<Span<int8_t>>(L::Partial(1, 0).Slice<int8_t>(p)).data()));
01106     EXPECT_EQ(
01107         4, Distance(
01108                p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<int32_t>(p)).data()));
01109     EXPECT_EQ(
01110         0,
01111         Distance(p, Type<Span<int8_t>>(L::Partial(5, 3).Slice<int8_t>(p)).data()));
01112     EXPECT_EQ(
01113         8, Distance(
01114                p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<int32_t>(p)).data()));
01115     EXPECT_EQ(
01116         0, Distance(
01117                p, Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<int8_t>(p)).data()));
01118     EXPECT_EQ(
01119         0,
01120         Distance(
01121             p, Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<int32_t>(p)).data()));
01122     EXPECT_EQ(
01123         0,
01124         Distance(
01125             p,
01126             Type<Span<Int128>>(L::Partial(0, 0, 0).Slice<Int128>(p)).data()));
01127     EXPECT_EQ(
01128         0, Distance(
01129                p, Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<int8_t>(p)).data()));
01130     EXPECT_EQ(
01131         4,
01132         Distance(
01133             p, Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<int32_t>(p)).data()));
01134     EXPECT_EQ(
01135         8,
01136         Distance(
01137             p,
01138             Type<Span<Int128>>(L::Partial(1, 0, 0).Slice<Int128>(p)).data()));
01139     EXPECT_EQ(
01140         0, Distance(
01141                p, Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<int8_t>(p)).data()));
01142     EXPECT_EQ(
01143         24,
01144         Distance(
01145             p,
01146             Type<Span<Int128>>(L::Partial(5, 3, 1).Slice<Int128>(p)).data()));
01147     EXPECT_EQ(
01148         8,
01149         Distance(
01150             p, Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<int32_t>(p)).data()));
01151     EXPECT_EQ(0,
01152               Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data()));
01153     EXPECT_EQ(
01154         24,
01155         Distance(p, Type<Span<Int128>>(L(5, 3, 1).Slice<Int128>(p)).data()));
01156     EXPECT_EQ(
01157         8, Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data()));
01158   }
01159 }
01160 
01161 MATCHER_P(IsSameSlice, slice, "") {
01162   return arg.size() == slice.size() && arg.data() == slice.data();
01163 }
01164 
01165 template <typename... M>
01166 class TupleMatcher {
01167  public:
01168   explicit TupleMatcher(M... matchers) : matchers_(std::move(matchers)...) {}
01169 
01170   template <typename Tuple>
01171   bool MatchAndExplain(const Tuple& p,
01172                        testing::MatchResultListener* /* listener */) const {
01173     static_assert(std::tuple_size<Tuple>::value == sizeof...(M), "");
01174     return MatchAndExplainImpl(
01175         p, absl::make_index_sequence<std::tuple_size<Tuple>::value>{});
01176   }
01177 
01178   // For the matcher concept. Left empty as we don't really need the diagnostics
01179   // right now.
01180   void DescribeTo(::std::ostream* os) const {}
01181   void DescribeNegationTo(::std::ostream* os) const {}
01182 
01183  private:
01184   template <typename Tuple, size_t... Is>
01185   bool MatchAndExplainImpl(const Tuple& p, absl::index_sequence<Is...>) const {
01186     // Using std::min as a simple variadic "and".
01187     return std::min(
01188         {true, testing::SafeMatcherCast<
01189                    const typename std::tuple_element<Is, Tuple>::type&>(
01190                    std::get<Is>(matchers_))
01191                    .Matches(std::get<Is>(p))...});
01192   }
01193 
01194   std::tuple<M...> matchers_;
01195 };
01196 
01197 template <typename... M>
01198 testing::PolymorphicMatcher<TupleMatcher<M...>> Tuple(M... matchers) {
01199   return testing::MakePolymorphicMatcher(
01200       TupleMatcher<M...>(std::move(matchers)...));
01201 }
01202 
01203 TEST(Layout, Slices) {
01204   alignas(max_align_t) const unsigned char p[100] = {};
01205   using L = Layout<int8_t, int8_t, Int128>;
01206   {
01207     const auto x = L::Partial();
01208     EXPECT_THAT(Type<std::tuple<>>(x.Slices(p)), Tuple());
01209   }
01210   {
01211     const auto x = L::Partial(1);
01212     EXPECT_THAT(Type<std::tuple<Span<const int8_t>>>(x.Slices(p)),
01213                 Tuple(IsSameSlice(x.Slice<0>(p))));
01214   }
01215   {
01216     const auto x = L::Partial(1, 2);
01217     EXPECT_THAT(
01218         (Type<std::tuple<Span<const int8_t>, Span<const int8_t>>>(x.Slices(p))),
01219         Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p))));
01220   }
01221   {
01222     const auto x = L::Partial(1, 2, 3);
01223     EXPECT_THAT((Type<std::tuple<Span<const int8_t>, Span<const int8_t>,
01224                                  Span<const Int128>>>(x.Slices(p))),
01225                 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
01226                       IsSameSlice(x.Slice<2>(p))));
01227   }
01228   {
01229     const L x(1, 2, 3);
01230     EXPECT_THAT((Type<std::tuple<Span<const int8_t>, Span<const int8_t>,
01231                                  Span<const Int128>>>(x.Slices(p))),
01232                 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
01233                       IsSameSlice(x.Slice<2>(p))));
01234   }
01235 }
01236 
01237 TEST(Layout, MutableSlices) {
01238   alignas(max_align_t) unsigned char p[100] = {};
01239   using L = Layout<int8_t, int8_t, Int128>;
01240   {
01241     const auto x = L::Partial();
01242     EXPECT_THAT(Type<std::tuple<>>(x.Slices(p)), Tuple());
01243   }
01244   {
01245     const auto x = L::Partial(1);
01246     EXPECT_THAT(Type<std::tuple<Span<int8_t>>>(x.Slices(p)),
01247                 Tuple(IsSameSlice(x.Slice<0>(p))));
01248   }
01249   {
01250     const auto x = L::Partial(1, 2);
01251     EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>>>(x.Slices(p))),
01252                 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p))));
01253   }
01254   {
01255     const auto x = L::Partial(1, 2, 3);
01256     EXPECT_THAT(
01257         (Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(x.Slices(p))),
01258         Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
01259               IsSameSlice(x.Slice<2>(p))));
01260   }
01261   {
01262     const L x(1, 2, 3);
01263     EXPECT_THAT(
01264         (Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>(x.Slices(p))),
01265         Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)),
01266               IsSameSlice(x.Slice<2>(p))));
01267   }
01268 }
01269 
01270 TEST(Layout, UnalignedTypes) {
01271   constexpr Layout<unsigned char, unsigned char, unsigned char> x(1, 2, 3);
01272   alignas(max_align_t) unsigned char p[x.AllocSize() + 1];
01273   EXPECT_THAT(x.Pointers(p + 1), Tuple(p + 1, p + 2, p + 4));
01274 }
01275 
01276 TEST(Layout, CustomAlignment) {
01277   constexpr Layout<unsigned char, Aligned<unsigned char, 8>> x(1, 2);
01278   alignas(max_align_t) unsigned char p[x.AllocSize()];
01279   EXPECT_EQ(10, x.AllocSize());
01280   EXPECT_THAT(x.Pointers(p), Tuple(p + 0, p + 8));
01281 }
01282 
01283 TEST(Layout, OverAligned) {
01284   constexpr size_t M = alignof(max_align_t);
01285   constexpr Layout<unsigned char, Aligned<unsigned char, 2 * M>> x(1, 3);
01286   alignas(2 * M) unsigned char p[x.AllocSize()];
01287   EXPECT_EQ(2 * M + 3, x.AllocSize());
01288   EXPECT_THAT(x.Pointers(p), Tuple(p + 0, p + 2 * M));
01289 }
01290 
01291 TEST(Layout, Alignment) {
01292   static_assert(Layout<int8_t>::Alignment() == 1, "");
01293   static_assert(Layout<int32_t>::Alignment() == 4, "");
01294   static_assert(Layout<Int64>::Alignment() == 8, "");
01295   static_assert(Layout<Aligned<int8_t, 64>>::Alignment() == 64, "");
01296   static_assert(Layout<int8_t, int32_t, Int64>::Alignment() == 8, "");
01297   static_assert(Layout<int8_t, Int64, int32_t>::Alignment() == 8, "");
01298   static_assert(Layout<int32_t, int8_t, Int64>::Alignment() == 8, "");
01299   static_assert(Layout<int32_t, Int64, int8_t>::Alignment() == 8, "");
01300   static_assert(Layout<Int64, int8_t, int32_t>::Alignment() == 8, "");
01301   static_assert(Layout<Int64, int32_t, int8_t>::Alignment() == 8, "");
01302 }
01303 
01304 TEST(Layout, ConstexprPartial) {
01305   constexpr size_t M = alignof(max_align_t);
01306   constexpr Layout<unsigned char, Aligned<unsigned char, 2 * M>> x(1, 3);
01307   static_assert(x.Partial(1).template Offset<1>() == 2 * M, "");
01308 }
01309 // [from, to)
01310 struct Region {
01311   size_t from;
01312   size_t to;
01313 };
01314 
01315 void ExpectRegionPoisoned(const unsigned char* p, size_t n, bool poisoned) {
01316 #ifdef ADDRESS_SANITIZER
01317   for (size_t i = 0; i != n; ++i) {
01318     EXPECT_EQ(poisoned, __asan_address_is_poisoned(p + i));
01319   }
01320 #endif
01321 }
01322 
01323 template <size_t N>
01324 void ExpectPoisoned(const unsigned char (&buf)[N],
01325                     std::initializer_list<Region> reg) {
01326   size_t prev = 0;
01327   for (const Region& r : reg) {
01328     ExpectRegionPoisoned(buf + prev, r.from - prev, false);
01329     ExpectRegionPoisoned(buf + r.from, r.to - r.from, true);
01330     prev = r.to;
01331   }
01332   ExpectRegionPoisoned(buf + prev, N - prev, false);
01333 }
01334 
01335 TEST(Layout, PoisonPadding) {
01336   using L = Layout<int8_t, Int64, int32_t, Int128>;
01337 
01338   constexpr size_t n = L::Partial(1, 2, 3, 4).AllocSize();
01339   {
01340     constexpr auto x = L::Partial();
01341     alignas(max_align_t) const unsigned char c[n] = {};
01342     x.PoisonPadding(c);
01343     EXPECT_EQ(x.Slices(c), x.Slices(c));
01344     ExpectPoisoned(c, {});
01345   }
01346   {
01347     constexpr auto x = L::Partial(1);
01348     alignas(max_align_t) const unsigned char c[n] = {};
01349     x.PoisonPadding(c);
01350     EXPECT_EQ(x.Slices(c), x.Slices(c));
01351     ExpectPoisoned(c, {{1, 8}});
01352   }
01353   {
01354     constexpr auto x = L::Partial(1, 2);
01355     alignas(max_align_t) const unsigned char c[n] = {};
01356     x.PoisonPadding(c);
01357     EXPECT_EQ(x.Slices(c), x.Slices(c));
01358     ExpectPoisoned(c, {{1, 8}});
01359   }
01360   {
01361     constexpr auto x = L::Partial(1, 2, 3);
01362     alignas(max_align_t) const unsigned char c[n] = {};
01363     x.PoisonPadding(c);
01364     EXPECT_EQ(x.Slices(c), x.Slices(c));
01365     ExpectPoisoned(c, {{1, 8}, {36, 40}});
01366   }
01367   {
01368     constexpr auto x = L::Partial(1, 2, 3, 4);
01369     alignas(max_align_t) const unsigned char c[n] = {};
01370     x.PoisonPadding(c);
01371     EXPECT_EQ(x.Slices(c), x.Slices(c));
01372     ExpectPoisoned(c, {{1, 8}, {36, 40}});
01373   }
01374   {
01375     constexpr L x(1, 2, 3, 4);
01376     alignas(max_align_t) const unsigned char c[n] = {};
01377     x.PoisonPadding(c);
01378     EXPECT_EQ(x.Slices(c), x.Slices(c));
01379     ExpectPoisoned(c, {{1, 8}, {36, 40}});
01380   }
01381 }
01382 
01383 TEST(Layout, DebugString) {
01384   {
01385     constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial();
01386     EXPECT_EQ("@0<signed char>(1)", x.DebugString());
01387   }
01388   {
01389     constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1);
01390     EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)", x.DebugString());
01391   }
01392   {
01393     constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2);
01394     EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)",
01395               x.DebugString());
01396   }
01397   {
01398     constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3);
01399     EXPECT_EQ(
01400         "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
01401         "@16" +
01402             Int128::Name() + "(16)",
01403         x.DebugString());
01404   }
01405   {
01406     constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3, 4);
01407     EXPECT_EQ(
01408         "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
01409         "@16" +
01410             Int128::Name() + "(16)[4]",
01411         x.DebugString());
01412   }
01413   {
01414     constexpr Layout<int8_t, int32_t, int8_t, Int128> x(1, 2, 3, 4);
01415     EXPECT_EQ(
01416         "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; "
01417         "@16" +
01418             Int128::Name() + "(16)[4]",
01419         x.DebugString());
01420   }
01421 }
01422 
01423 TEST(Layout, CharTypes) {
01424   constexpr Layout<int32_t> x(1);
01425   alignas(max_align_t) char c[x.AllocSize()] = {};
01426   alignas(max_align_t) unsigned char uc[x.AllocSize()] = {};
01427   alignas(max_align_t) signed char sc[x.AllocSize()] = {};
01428   alignas(max_align_t) const char cc[x.AllocSize()] = {};
01429   alignas(max_align_t) const unsigned char cuc[x.AllocSize()] = {};
01430   alignas(max_align_t) const signed char csc[x.AllocSize()] = {};
01431 
01432   Type<int32_t*>(x.Pointer<0>(c));
01433   Type<int32_t*>(x.Pointer<0>(uc));
01434   Type<int32_t*>(x.Pointer<0>(sc));
01435   Type<const int32_t*>(x.Pointer<0>(cc));
01436   Type<const int32_t*>(x.Pointer<0>(cuc));
01437   Type<const int32_t*>(x.Pointer<0>(csc));
01438 
01439   Type<int32_t*>(x.Pointer<int32_t>(c));
01440   Type<int32_t*>(x.Pointer<int32_t>(uc));
01441   Type<int32_t*>(x.Pointer<int32_t>(sc));
01442   Type<const int32_t*>(x.Pointer<int32_t>(cc));
01443   Type<const int32_t*>(x.Pointer<int32_t>(cuc));
01444   Type<const int32_t*>(x.Pointer<int32_t>(csc));
01445 
01446   Type<std::tuple<int32_t*>>(x.Pointers(c));
01447   Type<std::tuple<int32_t*>>(x.Pointers(uc));
01448   Type<std::tuple<int32_t*>>(x.Pointers(sc));
01449   Type<std::tuple<const int32_t*>>(x.Pointers(cc));
01450   Type<std::tuple<const int32_t*>>(x.Pointers(cuc));
01451   Type<std::tuple<const int32_t*>>(x.Pointers(csc));
01452 
01453   Type<Span<int32_t>>(x.Slice<0>(c));
01454   Type<Span<int32_t>>(x.Slice<0>(uc));
01455   Type<Span<int32_t>>(x.Slice<0>(sc));
01456   Type<Span<const int32_t>>(x.Slice<0>(cc));
01457   Type<Span<const int32_t>>(x.Slice<0>(cuc));
01458   Type<Span<const int32_t>>(x.Slice<0>(csc));
01459 
01460   Type<std::tuple<Span<int32_t>>>(x.Slices(c));
01461   Type<std::tuple<Span<int32_t>>>(x.Slices(uc));
01462   Type<std::tuple<Span<int32_t>>>(x.Slices(sc));
01463   Type<std::tuple<Span<const int32_t>>>(x.Slices(cc));
01464   Type<std::tuple<Span<const int32_t>>>(x.Slices(cuc));
01465   Type<std::tuple<Span<const int32_t>>>(x.Slices(csc));
01466 }
01467 
01468 TEST(Layout, ConstElementType) {
01469   constexpr Layout<const int32_t> x(1);
01470   alignas(int32_t) char c[x.AllocSize()] = {};
01471   const char* cc = c;
01472   const int32_t* p = reinterpret_cast<const int32_t*>(cc);
01473 
01474   EXPECT_EQ(alignof(int32_t), x.Alignment());
01475 
01476   EXPECT_EQ(0, x.Offset<0>());
01477   EXPECT_EQ(0, x.Offset<const int32_t>());
01478 
01479   EXPECT_THAT(x.Offsets(), ElementsAre(0));
01480 
01481   EXPECT_EQ(1, x.Size<0>());
01482   EXPECT_EQ(1, x.Size<const int32_t>());
01483 
01484   EXPECT_THAT(x.Sizes(), ElementsAre(1));
01485 
01486   EXPECT_EQ(sizeof(int32_t), x.AllocSize());
01487 
01488   EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<0>(c)));
01489   EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<0>(cc)));
01490 
01491   EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<const int32_t>(c)));
01492   EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<const int32_t>(cc)));
01493 
01494   EXPECT_THAT(Type<std::tuple<const int32_t*>>(x.Pointers(c)), Tuple(p));
01495   EXPECT_THAT(Type<std::tuple<const int32_t*>>(x.Pointers(cc)), Tuple(p));
01496 
01497   EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<0>(c)),
01498               IsSameSlice(Span<const int32_t>(p, 1)));
01499   EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<0>(cc)),
01500               IsSameSlice(Span<const int32_t>(p, 1)));
01501 
01502   EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<const int32_t>(c)),
01503               IsSameSlice(Span<const int32_t>(p, 1)));
01504   EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<const int32_t>(cc)),
01505               IsSameSlice(Span<const int32_t>(p, 1)));
01506 
01507   EXPECT_THAT(Type<std::tuple<Span<const int32_t>>>(x.Slices(c)),
01508               Tuple(IsSameSlice(Span<const int32_t>(p, 1))));
01509   EXPECT_THAT(Type<std::tuple<Span<const int32_t>>>(x.Slices(cc)),
01510               Tuple(IsSameSlice(Span<const int32_t>(p, 1))));
01511 }
01512 
01513 namespace example {
01514 
01515 // Immutable move-only string with sizeof equal to sizeof(void*). The string
01516 // size and the characters are kept in the same heap allocation.
01517 class CompactString {
01518  public:
01519   CompactString(const char* s = "") {  // NOLINT
01520     const size_t size = strlen(s);
01521     // size_t[1], followed by char[size + 1].
01522     // This statement doesn't allocate memory.
01523     const L layout(1, size + 1);
01524     // AllocSize() tells us how much memory we need to allocate for all our
01525     // data.
01526     p_.reset(new unsigned char[layout.AllocSize()]);
01527     // If running under ASAN, mark the padding bytes, if any, to catch memory
01528     // errors.
01529     layout.PoisonPadding(p_.get());
01530     // Store the size in the allocation.
01531     // Pointer<size_t>() is a synonym for Pointer<0>().
01532     *layout.Pointer<size_t>(p_.get()) = size;
01533     // Store the characters in the allocation.
01534     memcpy(layout.Pointer<char>(p_.get()), s, size + 1);
01535   }
01536 
01537   size_t size() const {
01538     // Equivalent to reinterpret_cast<size_t&>(*p).
01539     return *L::Partial().Pointer<size_t>(p_.get());
01540   }
01541 
01542   const char* c_str() const {
01543     // Equivalent to reinterpret_cast<char*>(p.get() + sizeof(size_t)).
01544     // The argument in Partial(1) specifies that we have size_t[1] in front of
01545     // the characters.
01546     return L::Partial(1).Pointer<char>(p_.get());
01547   }
01548 
01549  private:
01550   // Our heap allocation contains a size_t followed by an array of chars.
01551   using L = Layout<size_t, char>;
01552   std::unique_ptr<unsigned char[]> p_;
01553 };
01554 
01555 TEST(CompactString, Works) {
01556   CompactString s = "hello";
01557   EXPECT_EQ(5, s.size());
01558   EXPECT_STREQ("hello", s.c_str());
01559 }
01560 
01561 }  // namespace example
01562 
01563 }  // namespace
01564 }  // namespace container_internal
01565 }  // namespace absl


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