layout_test.cc (75816B)
1 // Copyright 2018 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "absl/container/internal/layout.h" 16 17 // We need ::max_align_t because some libstdc++ versions don't provide 18 // std::max_align_t 19 #include <stddef.h> 20 21 #include <cstdint> 22 #include <cstring> 23 #include <initializer_list> 24 #include <memory> 25 #include <ostream> 26 #include <string> 27 #include <tuple> 28 #include <type_traits> 29 30 #include "gmock/gmock.h" 31 #include "gtest/gtest.h" 32 #include "absl/base/config.h" 33 #include "absl/log/check.h" 34 #include "absl/types/span.h" 35 #include "absl/utility/utility.h" 36 37 namespace absl { 38 ABSL_NAMESPACE_BEGIN 39 namespace container_internal { 40 namespace { 41 42 using ::absl::Span; 43 using ::testing::ElementsAre; 44 45 size_t Distance(const void* from, const void* to) { 46 CHECK_LE(from, to) << "Distance must be non-negative"; 47 return static_cast<const char*>(to) - static_cast<const char*>(from); 48 } 49 50 template <class Expected, class Actual> 51 Expected Type(Actual val) { 52 static_assert(std::is_same<Expected, Actual>(), ""); 53 return val; 54 } 55 56 // Helper classes to test different size and alignments. 57 struct alignas(8) Int128 { 58 uint64_t a, b; 59 friend bool operator==(Int128 lhs, Int128 rhs) { 60 return std::tie(lhs.a, lhs.b) == std::tie(rhs.a, rhs.b); 61 } 62 63 static std::string Name() { 64 return internal_layout::adl_barrier::TypeName<Int128>(); 65 } 66 }; 67 68 // int64_t is *not* 8-byte aligned on all platforms! 69 struct alignas(8) Int64 { 70 int64_t a; 71 friend bool operator==(Int64 lhs, Int64 rhs) { return lhs.a == rhs.a; } 72 }; 73 74 // Properties of types that this test relies on. 75 static_assert(sizeof(int8_t) == 1, ""); 76 static_assert(alignof(int8_t) == 1, ""); 77 static_assert(sizeof(int16_t) == 2, ""); 78 static_assert(alignof(int16_t) == 2, ""); 79 static_assert(sizeof(int32_t) == 4, ""); 80 static_assert(alignof(int32_t) == 4, ""); 81 static_assert(sizeof(Int64) == 8, ""); 82 static_assert(alignof(Int64) == 8, ""); 83 static_assert(sizeof(Int128) == 16, ""); 84 static_assert(alignof(Int128) == 8, ""); 85 86 template <class Expected, class Actual> 87 void SameType() { 88 static_assert(std::is_same<Expected, Actual>(), ""); 89 } 90 91 TEST(Layout, ElementType) { 92 { 93 using L = Layout<int32_t>; 94 SameType<int32_t, L::ElementType<0>>(); 95 SameType<int32_t, decltype(L::Partial())::ElementType<0>>(); 96 SameType<int32_t, decltype(L::Partial(0))::ElementType<0>>(); 97 } 98 { 99 using L = Layout<int32_t, int32_t>; 100 SameType<int32_t, L::ElementType<0>>(); 101 SameType<int32_t, L::ElementType<1>>(); 102 SameType<int32_t, decltype(L::Partial())::ElementType<0>>(); 103 SameType<int32_t, decltype(L::Partial())::ElementType<1>>(); 104 SameType<int32_t, decltype(L::Partial(0))::ElementType<0>>(); 105 SameType<int32_t, decltype(L::Partial(0))::ElementType<1>>(); 106 } 107 { 108 using L = Layout<int8_t, int32_t, Int128>; 109 SameType<int8_t, L::ElementType<0>>(); 110 SameType<int32_t, L::ElementType<1>>(); 111 SameType<Int128, L::ElementType<2>>(); 112 SameType<int8_t, decltype(L::Partial())::ElementType<0>>(); 113 SameType<int8_t, decltype(L::Partial(0))::ElementType<0>>(); 114 SameType<int32_t, decltype(L::Partial(0))::ElementType<1>>(); 115 SameType<int8_t, decltype(L::Partial(0, 0))::ElementType<0>>(); 116 SameType<int32_t, decltype(L::Partial(0, 0))::ElementType<1>>(); 117 SameType<Int128, decltype(L::Partial(0, 0))::ElementType<2>>(); 118 SameType<int8_t, decltype(L::Partial(0, 0, 0))::ElementType<0>>(); 119 SameType<int32_t, decltype(L::Partial(0, 0, 0))::ElementType<1>>(); 120 SameType<Int128, decltype(L::Partial(0, 0, 0))::ElementType<2>>(); 121 } 122 } 123 124 TEST(Layout, ElementTypes) { 125 { 126 using L = Layout<int32_t>; 127 SameType<std::tuple<int32_t>, L::ElementTypes>(); 128 SameType<std::tuple<int32_t>, decltype(L::Partial())::ElementTypes>(); 129 SameType<std::tuple<int32_t>, decltype(L::Partial(0))::ElementTypes>(); 130 } 131 { 132 using L = Layout<int32_t, int32_t>; 133 SameType<std::tuple<int32_t, int32_t>, L::ElementTypes>(); 134 SameType<std::tuple<int32_t, int32_t>, 135 decltype(L::Partial())::ElementTypes>(); 136 SameType<std::tuple<int32_t, int32_t>, 137 decltype(L::Partial(0))::ElementTypes>(); 138 } 139 { 140 using L = Layout<int8_t, int32_t, Int128>; 141 SameType<std::tuple<int8_t, int32_t, Int128>, L::ElementTypes>(); 142 SameType<std::tuple<int8_t, int32_t, Int128>, 143 decltype(L::Partial())::ElementTypes>(); 144 SameType<std::tuple<int8_t, int32_t, Int128>, 145 decltype(L::Partial(0))::ElementTypes>(); 146 SameType<std::tuple<int8_t, int32_t, Int128>, 147 decltype(L::Partial(0, 0))::ElementTypes>(); 148 SameType<std::tuple<int8_t, int32_t, Int128>, 149 decltype(L::Partial(0, 0, 0))::ElementTypes>(); 150 } 151 } 152 153 TEST(Layout, OffsetByIndex) { 154 { 155 using L = Layout<int32_t>; 156 EXPECT_EQ(0, L::Partial().Offset<0>()); 157 EXPECT_EQ(0, L::Partial(3).Offset<0>()); 158 EXPECT_EQ(0, L(3).Offset<0>()); 159 } 160 { 161 using L = Layout<int32_t, int32_t>; 162 EXPECT_EQ(0, L::Partial().Offset<0>()); 163 EXPECT_EQ(0, L::Partial(3).Offset<0>()); 164 EXPECT_EQ(12, L::Partial(3).Offset<1>()); 165 EXPECT_EQ(0, L::Partial(3, 5).Offset<0>()); 166 EXPECT_EQ(12, L::Partial(3, 5).Offset<1>()); 167 EXPECT_EQ(0, L(3, 5).Offset<0>()); 168 EXPECT_EQ(12, L(3, 5).Offset<1>()); 169 } 170 { 171 using L = Layout<int8_t, int32_t, Int128>; 172 EXPECT_EQ(0, L::Partial().Offset<0>()); 173 EXPECT_EQ(0, L::Partial(0).Offset<0>()); 174 EXPECT_EQ(0, L::Partial(0).Offset<1>()); 175 EXPECT_EQ(0, L::Partial(1).Offset<0>()); 176 EXPECT_EQ(4, L::Partial(1).Offset<1>()); 177 EXPECT_EQ(0, L::Partial(5).Offset<0>()); 178 EXPECT_EQ(8, L::Partial(5).Offset<1>()); 179 EXPECT_EQ(0, L::Partial(0, 0).Offset<0>()); 180 EXPECT_EQ(0, L::Partial(0, 0).Offset<1>()); 181 EXPECT_EQ(0, L::Partial(0, 0).Offset<2>()); 182 EXPECT_EQ(0, L::Partial(1, 0).Offset<0>()); 183 EXPECT_EQ(4, L::Partial(1, 0).Offset<1>()); 184 EXPECT_EQ(8, L::Partial(1, 0).Offset<2>()); 185 EXPECT_EQ(0, L::Partial(5, 3).Offset<0>()); 186 EXPECT_EQ(8, L::Partial(5, 3).Offset<1>()); 187 EXPECT_EQ(24, L::Partial(5, 3).Offset<2>()); 188 EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<0>()); 189 EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<1>()); 190 EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<2>()); 191 EXPECT_EQ(0, L::Partial(1, 0, 0).Offset<0>()); 192 EXPECT_EQ(4, L::Partial(1, 0, 0).Offset<1>()); 193 EXPECT_EQ(8, L::Partial(1, 0, 0).Offset<2>()); 194 EXPECT_EQ(0, L::Partial(5, 3, 1).Offset<0>()); 195 EXPECT_EQ(24, L::Partial(5, 3, 1).Offset<2>()); 196 EXPECT_EQ(8, L::Partial(5, 3, 1).Offset<1>()); 197 EXPECT_EQ(0, L(5, 3, 1).Offset<0>()); 198 EXPECT_EQ(24, L(5, 3, 1).Offset<2>()); 199 EXPECT_EQ(8, L(5, 3, 1).Offset<1>()); 200 } 201 } 202 203 TEST(Layout, OffsetByType) { 204 { 205 using L = Layout<int32_t>; 206 EXPECT_EQ(0, L::Partial().Offset<int32_t>()); 207 EXPECT_EQ(0, L::Partial(3).Offset<int32_t>()); 208 EXPECT_EQ(0, L(3).Offset<int32_t>()); 209 } 210 { 211 using L = Layout<int8_t, int32_t, Int128>; 212 EXPECT_EQ(0, L::Partial().Offset<int8_t>()); 213 EXPECT_EQ(0, L::Partial(0).Offset<int8_t>()); 214 EXPECT_EQ(0, L::Partial(0).Offset<int32_t>()); 215 EXPECT_EQ(0, L::Partial(1).Offset<int8_t>()); 216 EXPECT_EQ(4, L::Partial(1).Offset<int32_t>()); 217 EXPECT_EQ(0, L::Partial(5).Offset<int8_t>()); 218 EXPECT_EQ(8, L::Partial(5).Offset<int32_t>()); 219 EXPECT_EQ(0, L::Partial(0, 0).Offset<int8_t>()); 220 EXPECT_EQ(0, L::Partial(0, 0).Offset<int32_t>()); 221 EXPECT_EQ(0, L::Partial(0, 0).Offset<Int128>()); 222 EXPECT_EQ(0, L::Partial(1, 0).Offset<int8_t>()); 223 EXPECT_EQ(4, L::Partial(1, 0).Offset<int32_t>()); 224 EXPECT_EQ(8, L::Partial(1, 0).Offset<Int128>()); 225 EXPECT_EQ(0, L::Partial(5, 3).Offset<int8_t>()); 226 EXPECT_EQ(8, L::Partial(5, 3).Offset<int32_t>()); 227 EXPECT_EQ(24, L::Partial(5, 3).Offset<Int128>()); 228 EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<int8_t>()); 229 EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<int32_t>()); 230 EXPECT_EQ(0, L::Partial(0, 0, 0).Offset<Int128>()); 231 EXPECT_EQ(0, L::Partial(1, 0, 0).Offset<int8_t>()); 232 EXPECT_EQ(4, L::Partial(1, 0, 0).Offset<int32_t>()); 233 EXPECT_EQ(8, L::Partial(1, 0, 0).Offset<Int128>()); 234 EXPECT_EQ(0, L::Partial(5, 3, 1).Offset<int8_t>()); 235 EXPECT_EQ(24, L::Partial(5, 3, 1).Offset<Int128>()); 236 EXPECT_EQ(8, L::Partial(5, 3, 1).Offset<int32_t>()); 237 EXPECT_EQ(0, L(5, 3, 1).Offset<int8_t>()); 238 EXPECT_EQ(24, L(5, 3, 1).Offset<Int128>()); 239 EXPECT_EQ(8, L(5, 3, 1).Offset<int32_t>()); 240 } 241 } 242 243 TEST(Layout, Offsets) { 244 { 245 using L = Layout<int32_t>; 246 EXPECT_THAT(L::Partial().Offsets(), ElementsAre(0)); 247 EXPECT_THAT(L::Partial(3).Offsets(), ElementsAre(0)); 248 EXPECT_THAT(L(3).Offsets(), ElementsAre(0)); 249 } 250 { 251 using L = Layout<int32_t, int32_t>; 252 EXPECT_THAT(L::Partial().Offsets(), ElementsAre(0)); 253 EXPECT_THAT(L::Partial(3).Offsets(), ElementsAre(0, 12)); 254 EXPECT_THAT(L::Partial(3, 5).Offsets(), ElementsAre(0, 12)); 255 EXPECT_THAT(L(3, 5).Offsets(), ElementsAre(0, 12)); 256 } 257 { 258 using L = Layout<int8_t, int32_t, Int128>; 259 EXPECT_THAT(L::Partial().Offsets(), ElementsAre(0)); 260 EXPECT_THAT(L::Partial(1).Offsets(), ElementsAre(0, 4)); 261 EXPECT_THAT(L::Partial(5).Offsets(), ElementsAre(0, 8)); 262 EXPECT_THAT(L::Partial(0, 0).Offsets(), ElementsAre(0, 0, 0)); 263 EXPECT_THAT(L::Partial(1, 0).Offsets(), ElementsAre(0, 4, 8)); 264 EXPECT_THAT(L::Partial(5, 3).Offsets(), ElementsAre(0, 8, 24)); 265 EXPECT_THAT(L::Partial(0, 0, 0).Offsets(), ElementsAre(0, 0, 0)); 266 EXPECT_THAT(L::Partial(1, 0, 0).Offsets(), ElementsAre(0, 4, 8)); 267 EXPECT_THAT(L::Partial(5, 3, 1).Offsets(), ElementsAre(0, 8, 24)); 268 EXPECT_THAT(L(5, 3, 1).Offsets(), ElementsAre(0, 8, 24)); 269 } 270 } 271 272 TEST(Layout, StaticOffsets) { 273 using L = Layout<int8_t, int32_t, Int128>; 274 { 275 using SL = L::WithStaticSizes<>; 276 EXPECT_THAT(SL::Partial().Offsets(), ElementsAre(0)); 277 EXPECT_THAT(SL::Partial(5).Offsets(), ElementsAre(0, 8)); 278 EXPECT_THAT(SL::Partial(5, 3, 1).Offsets(), ElementsAre(0, 8, 24)); 279 EXPECT_THAT(SL(5, 3, 1).Offsets(), ElementsAre(0, 8, 24)); 280 } 281 { 282 using SL = L::WithStaticSizes<5>; 283 EXPECT_THAT(SL::Partial().Offsets(), ElementsAre(0, 8)); 284 EXPECT_THAT(SL::Partial(3).Offsets(), ElementsAre(0, 8, 24)); 285 EXPECT_THAT(SL::Partial(3, 1).Offsets(), ElementsAre(0, 8, 24)); 286 EXPECT_THAT(SL(3, 1).Offsets(), ElementsAre(0, 8, 24)); 287 } 288 { 289 using SL = L::WithStaticSizes<5, 3>; 290 EXPECT_THAT(SL::Partial().Offsets(), ElementsAre(0, 8, 24)); 291 EXPECT_THAT(SL::Partial(1).Offsets(), ElementsAre(0, 8, 24)); 292 EXPECT_THAT(SL(1).Offsets(), ElementsAre(0, 8, 24)); 293 } 294 { 295 using SL = L::WithStaticSizes<5, 3, 1>; 296 EXPECT_THAT(SL::Partial().Offsets(), ElementsAre(0, 8, 24)); 297 EXPECT_THAT(SL().Offsets(), ElementsAre(0, 8, 24)); 298 } 299 } 300 301 TEST(Layout, AllocSize) { 302 { 303 using L = Layout<int32_t>; 304 EXPECT_EQ(0, L::Partial(0).AllocSize()); 305 EXPECT_EQ(12, L::Partial(3).AllocSize()); 306 EXPECT_EQ(12, L(3).AllocSize()); 307 } 308 { 309 using L = Layout<int32_t, int32_t>; 310 EXPECT_EQ(32, L::Partial(3, 5).AllocSize()); 311 EXPECT_EQ(32, L(3, 5).AllocSize()); 312 } 313 { 314 using L = Layout<int8_t, int32_t, Int128>; 315 EXPECT_EQ(0, L::Partial(0, 0, 0).AllocSize()); 316 EXPECT_EQ(8, L::Partial(1, 0, 0).AllocSize()); 317 EXPECT_EQ(8, L::Partial(0, 1, 0).AllocSize()); 318 EXPECT_EQ(16, L::Partial(0, 0, 1).AllocSize()); 319 EXPECT_EQ(24, L::Partial(1, 1, 1).AllocSize()); 320 EXPECT_EQ(136, L::Partial(3, 5, 7).AllocSize()); 321 EXPECT_EQ(136, L(3, 5, 7).AllocSize()); 322 } 323 } 324 325 TEST(Layout, StaticAllocSize) { 326 using L = Layout<int8_t, int32_t, Int128>; 327 { 328 using SL = L::WithStaticSizes<>; 329 EXPECT_EQ(136, SL::Partial(3, 5, 7).AllocSize()); 330 EXPECT_EQ(136, SL(3, 5, 7).AllocSize()); 331 } 332 { 333 using SL = L::WithStaticSizes<3>; 334 EXPECT_EQ(136, SL::Partial(5, 7).AllocSize()); 335 EXPECT_EQ(136, SL(5, 7).AllocSize()); 336 } 337 { 338 using SL = L::WithStaticSizes<3, 5>; 339 EXPECT_EQ(136, SL::Partial(7).AllocSize()); 340 EXPECT_EQ(136, SL(7).AllocSize()); 341 } 342 { 343 using SL = L::WithStaticSizes<3, 5, 7>; 344 EXPECT_EQ(136, SL::Partial().AllocSize()); 345 EXPECT_EQ(136, SL().AllocSize()); 346 } 347 } 348 349 TEST(Layout, SizeByIndex) { 350 { 351 using L = Layout<int32_t>; 352 EXPECT_EQ(0, L::Partial(0).Size<0>()); 353 EXPECT_EQ(3, L::Partial(3).Size<0>()); 354 EXPECT_EQ(3, L(3).Size<0>()); 355 } 356 { 357 using L = Layout<int32_t, int32_t>; 358 EXPECT_EQ(0, L::Partial(0).Size<0>()); 359 EXPECT_EQ(3, L::Partial(3).Size<0>()); 360 EXPECT_EQ(3, L::Partial(3, 5).Size<0>()); 361 EXPECT_EQ(5, L::Partial(3, 5).Size<1>()); 362 EXPECT_EQ(3, L(3, 5).Size<0>()); 363 EXPECT_EQ(5, L(3, 5).Size<1>()); 364 } 365 { 366 using L = Layout<int8_t, int32_t, Int128>; 367 EXPECT_EQ(3, L::Partial(3).Size<0>()); 368 EXPECT_EQ(3, L::Partial(3, 5).Size<0>()); 369 EXPECT_EQ(5, L::Partial(3, 5).Size<1>()); 370 EXPECT_EQ(3, L::Partial(3, 5, 7).Size<0>()); 371 EXPECT_EQ(5, L::Partial(3, 5, 7).Size<1>()); 372 EXPECT_EQ(7, L::Partial(3, 5, 7).Size<2>()); 373 EXPECT_EQ(3, L(3, 5, 7).Size<0>()); 374 EXPECT_EQ(5, L(3, 5, 7).Size<1>()); 375 EXPECT_EQ(7, L(3, 5, 7).Size<2>()); 376 } 377 } 378 379 TEST(Layout, SizeByType) { 380 { 381 using L = Layout<int32_t>; 382 EXPECT_EQ(0, L::Partial(0).Size<int32_t>()); 383 EXPECT_EQ(3, L::Partial(3).Size<int32_t>()); 384 EXPECT_EQ(3, L(3).Size<int32_t>()); 385 } 386 { 387 using L = Layout<int8_t, int32_t, Int128>; 388 EXPECT_EQ(3, L::Partial(3).Size<int8_t>()); 389 EXPECT_EQ(3, L::Partial(3, 5).Size<int8_t>()); 390 EXPECT_EQ(5, L::Partial(3, 5).Size<int32_t>()); 391 EXPECT_EQ(3, L::Partial(3, 5, 7).Size<int8_t>()); 392 EXPECT_EQ(5, L::Partial(3, 5, 7).Size<int32_t>()); 393 EXPECT_EQ(7, L::Partial(3, 5, 7).Size<Int128>()); 394 EXPECT_EQ(3, L(3, 5, 7).Size<int8_t>()); 395 EXPECT_EQ(5, L(3, 5, 7).Size<int32_t>()); 396 EXPECT_EQ(7, L(3, 5, 7).Size<Int128>()); 397 } 398 } 399 400 TEST(Layout, Sizes) { 401 { 402 using L = Layout<int32_t>; 403 EXPECT_THAT(L::Partial().Sizes(), ElementsAre()); 404 EXPECT_THAT(L::Partial(3).Sizes(), ElementsAre(3)); 405 EXPECT_THAT(L(3).Sizes(), ElementsAre(3)); 406 } 407 { 408 using L = Layout<int32_t, int32_t>; 409 EXPECT_THAT(L::Partial().Sizes(), ElementsAre()); 410 EXPECT_THAT(L::Partial(3).Sizes(), ElementsAre(3)); 411 EXPECT_THAT(L::Partial(3, 5).Sizes(), ElementsAre(3, 5)); 412 EXPECT_THAT(L(3, 5).Sizes(), ElementsAre(3, 5)); 413 } 414 { 415 using L = Layout<int8_t, int32_t, Int128>; 416 EXPECT_THAT(L::Partial().Sizes(), ElementsAre()); 417 EXPECT_THAT(L::Partial(3).Sizes(), ElementsAre(3)); 418 EXPECT_THAT(L::Partial(3, 5).Sizes(), ElementsAre(3, 5)); 419 EXPECT_THAT(L::Partial(3, 5, 7).Sizes(), ElementsAre(3, 5, 7)); 420 EXPECT_THAT(L(3, 5, 7).Sizes(), ElementsAre(3, 5, 7)); 421 } 422 } 423 424 TEST(Layout, StaticSize) { 425 using L = Layout<int8_t, int32_t, Int128>; 426 { 427 using SL = L::WithStaticSizes<>; 428 EXPECT_THAT(SL::Partial().Sizes(), ElementsAre()); 429 EXPECT_THAT(SL::Partial(3).Size<0>(), 3); 430 EXPECT_THAT(SL::Partial(3).Size<int8_t>(), 3); 431 EXPECT_THAT(SL::Partial(3).Sizes(), ElementsAre(3)); 432 EXPECT_THAT(SL::Partial(3, 5, 7).Size<0>(), 3); 433 EXPECT_THAT(SL::Partial(3, 5, 7).Size<int8_t>(), 3); 434 EXPECT_THAT(SL::Partial(3, 5, 7).Size<2>(), 7); 435 EXPECT_THAT(SL::Partial(3, 5, 7).Size<Int128>(), 7); 436 EXPECT_THAT(SL::Partial(3, 5, 7).Sizes(), ElementsAre(3, 5, 7)); 437 EXPECT_THAT(SL(3, 5, 7).Size<0>(), 3); 438 EXPECT_THAT(SL(3, 5, 7).Size<int8_t>(), 3); 439 EXPECT_THAT(SL(3, 5, 7).Size<2>(), 7); 440 EXPECT_THAT(SL(3, 5, 7).Size<Int128>(), 7); 441 EXPECT_THAT(SL(3, 5, 7).Sizes(), ElementsAre(3, 5, 7)); 442 } 443 } 444 445 TEST(Layout, PointerByIndex) { 446 alignas(max_align_t) const unsigned char p[100] = {0}; 447 { 448 using L = Layout<int32_t>; 449 EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<0>(p)))); 450 EXPECT_EQ(0, 451 Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p)))); 452 EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3).Pointer<0>(p)))); 453 } 454 { 455 using L = Layout<int32_t, int32_t>; 456 EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<0>(p)))); 457 EXPECT_EQ(0, 458 Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<0>(p)))); 459 EXPECT_EQ(12, 460 Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<1>(p)))); 461 EXPECT_EQ( 462 0, Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<0>(p)))); 463 EXPECT_EQ( 464 12, Distance(p, Type<const int32_t*>(L::Partial(3, 5).Pointer<1>(p)))); 465 EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3, 5).Pointer<0>(p)))); 466 EXPECT_EQ(12, Distance(p, Type<const int32_t*>(L(3, 5).Pointer<1>(p)))); 467 } 468 { 469 using L = Layout<int8_t, int32_t, Int128>; 470 EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<0>(p)))); 471 EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<0>(p)))); 472 EXPECT_EQ(0, 473 Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<1>(p)))); 474 EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<0>(p)))); 475 EXPECT_EQ(4, 476 Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<1>(p)))); 477 EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<0>(p)))); 478 EXPECT_EQ(8, 479 Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<1>(p)))); 480 EXPECT_EQ(0, 481 Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<0>(p)))); 482 EXPECT_EQ( 483 0, Distance(p, Type<const int32_t*>(L::Partial(0, 0).Pointer<1>(p)))); 484 EXPECT_EQ(0, 485 Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<2>(p)))); 486 EXPECT_EQ(0, 487 Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<0>(p)))); 488 EXPECT_EQ( 489 4, Distance(p, Type<const int32_t*>(L::Partial(1, 0).Pointer<1>(p)))); 490 EXPECT_EQ(8, 491 Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<2>(p)))); 492 EXPECT_EQ(0, 493 Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<0>(p)))); 494 EXPECT_EQ( 495 8, Distance(p, Type<const int32_t*>(L::Partial(5, 3).Pointer<1>(p)))); 496 EXPECT_EQ(24, 497 Distance(p, Type<const Int128*>(L::Partial(5, 3).Pointer<2>(p)))); 498 EXPECT_EQ( 499 0, Distance(p, Type<const int8_t*>(L::Partial(0, 0, 0).Pointer<0>(p)))); 500 EXPECT_EQ( 501 0, 502 Distance(p, Type<const int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p)))); 503 EXPECT_EQ( 504 0, Distance(p, Type<const Int128*>(L::Partial(0, 0, 0).Pointer<2>(p)))); 505 EXPECT_EQ( 506 0, Distance(p, Type<const int8_t*>(L::Partial(1, 0, 0).Pointer<0>(p)))); 507 EXPECT_EQ( 508 4, 509 Distance(p, Type<const int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p)))); 510 EXPECT_EQ( 511 8, Distance(p, Type<const Int128*>(L::Partial(1, 0, 0).Pointer<2>(p)))); 512 EXPECT_EQ( 513 0, Distance(p, Type<const int8_t*>(L::Partial(5, 3, 1).Pointer<0>(p)))); 514 EXPECT_EQ( 515 24, 516 Distance(p, Type<const Int128*>(L::Partial(5, 3, 1).Pointer<2>(p)))); 517 EXPECT_EQ( 518 8, 519 Distance(p, Type<const int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p)))); 520 EXPECT_EQ(0, Distance(p, Type<const int8_t*>(L(5, 3, 1).Pointer<0>(p)))); 521 EXPECT_EQ(24, Distance(p, Type<const Int128*>(L(5, 3, 1).Pointer<2>(p)))); 522 EXPECT_EQ(8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<1>(p)))); 523 } 524 } 525 526 TEST(Layout, PointerByType) { 527 alignas(max_align_t) const unsigned char p[100] = {0}; 528 { 529 using L = Layout<int32_t>; 530 EXPECT_EQ( 531 0, Distance(p, Type<const int32_t*>(L::Partial().Pointer<int32_t>(p)))); 532 EXPECT_EQ( 533 0, 534 Distance(p, Type<const int32_t*>(L::Partial(3).Pointer<int32_t>(p)))); 535 EXPECT_EQ(0, Distance(p, Type<const int32_t*>(L(3).Pointer<int32_t>(p)))); 536 } 537 { 538 using L = Layout<int8_t, int32_t, Int128>; 539 EXPECT_EQ( 540 0, Distance(p, Type<const int8_t*>(L::Partial().Pointer<int8_t>(p)))); 541 EXPECT_EQ( 542 0, Distance(p, Type<const int8_t*>(L::Partial(0).Pointer<int8_t>(p)))); 543 EXPECT_EQ( 544 0, 545 Distance(p, Type<const int32_t*>(L::Partial(0).Pointer<int32_t>(p)))); 546 EXPECT_EQ( 547 0, Distance(p, Type<const int8_t*>(L::Partial(1).Pointer<int8_t>(p)))); 548 EXPECT_EQ( 549 4, 550 Distance(p, Type<const int32_t*>(L::Partial(1).Pointer<int32_t>(p)))); 551 EXPECT_EQ( 552 0, Distance(p, Type<const int8_t*>(L::Partial(5).Pointer<int8_t>(p)))); 553 EXPECT_EQ( 554 8, 555 Distance(p, Type<const int32_t*>(L::Partial(5).Pointer<int32_t>(p)))); 556 EXPECT_EQ( 557 0, 558 Distance(p, Type<const int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p)))); 559 EXPECT_EQ(0, Distance(p, Type<const int32_t*>( 560 L::Partial(0, 0).Pointer<int32_t>(p)))); 561 EXPECT_EQ( 562 0, 563 Distance(p, Type<const Int128*>(L::Partial(0, 0).Pointer<Int128>(p)))); 564 EXPECT_EQ( 565 0, 566 Distance(p, Type<const int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p)))); 567 EXPECT_EQ(4, Distance(p, Type<const int32_t*>( 568 L::Partial(1, 0).Pointer<int32_t>(p)))); 569 EXPECT_EQ( 570 8, 571 Distance(p, Type<const Int128*>(L::Partial(1, 0).Pointer<Int128>(p)))); 572 EXPECT_EQ( 573 0, 574 Distance(p, Type<const int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p)))); 575 EXPECT_EQ(8, Distance(p, Type<const int32_t*>( 576 L::Partial(5, 3).Pointer<int32_t>(p)))); 577 EXPECT_EQ( 578 24, 579 Distance(p, Type<const Int128*>(L::Partial(5, 3).Pointer<Int128>(p)))); 580 EXPECT_EQ(0, Distance(p, Type<const int8_t*>( 581 L::Partial(0, 0, 0).Pointer<int8_t>(p)))); 582 EXPECT_EQ(0, Distance(p, Type<const int32_t*>( 583 L::Partial(0, 0, 0).Pointer<int32_t>(p)))); 584 EXPECT_EQ(0, Distance(p, Type<const Int128*>( 585 L::Partial(0, 0, 0).Pointer<Int128>(p)))); 586 EXPECT_EQ(0, Distance(p, Type<const int8_t*>( 587 L::Partial(1, 0, 0).Pointer<int8_t>(p)))); 588 EXPECT_EQ(4, Distance(p, Type<const int32_t*>( 589 L::Partial(1, 0, 0).Pointer<int32_t>(p)))); 590 EXPECT_EQ(8, Distance(p, Type<const Int128*>( 591 L::Partial(1, 0, 0).Pointer<Int128>(p)))); 592 EXPECT_EQ(0, Distance(p, Type<const int8_t*>( 593 L::Partial(5, 3, 1).Pointer<int8_t>(p)))); 594 EXPECT_EQ(24, Distance(p, Type<const Int128*>( 595 L::Partial(5, 3, 1).Pointer<Int128>(p)))); 596 EXPECT_EQ(8, Distance(p, Type<const int32_t*>( 597 L::Partial(5, 3, 1).Pointer<int32_t>(p)))); 598 EXPECT_EQ(24, 599 Distance(p, Type<const Int128*>(L(5, 3, 1).Pointer<Int128>(p)))); 600 EXPECT_EQ( 601 8, Distance(p, Type<const int32_t*>(L(5, 3, 1).Pointer<int32_t>(p)))); 602 } 603 } 604 605 TEST(Layout, MutablePointerByIndex) { 606 alignas(max_align_t) unsigned char p[100] = {0}; 607 { 608 using L = Layout<int32_t>; 609 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<0>(p)))); 610 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<0>(p)))); 611 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3).Pointer<0>(p)))); 612 } 613 { 614 using L = Layout<int32_t, int32_t>; 615 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<0>(p)))); 616 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<0>(p)))); 617 EXPECT_EQ(12, Distance(p, Type<int32_t*>(L::Partial(3).Pointer<1>(p)))); 618 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(3, 5).Pointer<0>(p)))); 619 EXPECT_EQ(12, Distance(p, Type<int32_t*>(L::Partial(3, 5).Pointer<1>(p)))); 620 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3, 5).Pointer<0>(p)))); 621 EXPECT_EQ(12, Distance(p, Type<int32_t*>(L(3, 5).Pointer<1>(p)))); 622 } 623 { 624 using L = Layout<int8_t, int32_t, Int128>; 625 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial().Pointer<0>(p)))); 626 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0).Pointer<0>(p)))); 627 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0).Pointer<1>(p)))); 628 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1).Pointer<0>(p)))); 629 EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1).Pointer<1>(p)))); 630 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5).Pointer<0>(p)))); 631 EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5).Pointer<1>(p)))); 632 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0, 0).Pointer<0>(p)))); 633 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial(0, 0).Pointer<1>(p)))); 634 EXPECT_EQ(0, Distance(p, Type<Int128*>(L::Partial(0, 0).Pointer<2>(p)))); 635 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1, 0).Pointer<0>(p)))); 636 EXPECT_EQ(4, Distance(p, Type<int32_t*>(L::Partial(1, 0).Pointer<1>(p)))); 637 EXPECT_EQ(8, Distance(p, Type<Int128*>(L::Partial(1, 0).Pointer<2>(p)))); 638 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5, 3).Pointer<0>(p)))); 639 EXPECT_EQ(8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<1>(p)))); 640 EXPECT_EQ(24, Distance(p, Type<Int128*>(L::Partial(5, 3).Pointer<2>(p)))); 641 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<0>(p)))); 642 EXPECT_EQ(0, 643 Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<1>(p)))); 644 EXPECT_EQ(0, Distance(p, Type<Int128*>(L::Partial(0, 0, 0).Pointer<2>(p)))); 645 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<0>(p)))); 646 EXPECT_EQ(4, 647 Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<1>(p)))); 648 EXPECT_EQ(8, Distance(p, Type<Int128*>(L::Partial(1, 0, 0).Pointer<2>(p)))); 649 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<0>(p)))); 650 EXPECT_EQ(24, 651 Distance(p, Type<Int128*>(L::Partial(5, 3, 1).Pointer<2>(p)))); 652 EXPECT_EQ(8, 653 Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<1>(p)))); 654 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L(5, 3, 1).Pointer<0>(p)))); 655 EXPECT_EQ(24, Distance(p, Type<Int128*>(L(5, 3, 1).Pointer<2>(p)))); 656 EXPECT_EQ(8, Distance(p, Type<int32_t*>(L(5, 3, 1).Pointer<1>(p)))); 657 } 658 } 659 660 TEST(Layout, MutablePointerByType) { 661 alignas(max_align_t) unsigned char p[100] = {0}; 662 { 663 using L = Layout<int32_t>; 664 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L::Partial().Pointer<int32_t>(p)))); 665 EXPECT_EQ(0, 666 Distance(p, Type<int32_t*>(L::Partial(3).Pointer<int32_t>(p)))); 667 EXPECT_EQ(0, Distance(p, Type<int32_t*>(L(3).Pointer<int32_t>(p)))); 668 } 669 { 670 using L = Layout<int8_t, int32_t, Int128>; 671 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial().Pointer<int8_t>(p)))); 672 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(0).Pointer<int8_t>(p)))); 673 EXPECT_EQ(0, 674 Distance(p, Type<int32_t*>(L::Partial(0).Pointer<int32_t>(p)))); 675 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(1).Pointer<int8_t>(p)))); 676 EXPECT_EQ(4, 677 Distance(p, Type<int32_t*>(L::Partial(1).Pointer<int32_t>(p)))); 678 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L::Partial(5).Pointer<int8_t>(p)))); 679 EXPECT_EQ(8, 680 Distance(p, Type<int32_t*>(L::Partial(5).Pointer<int32_t>(p)))); 681 EXPECT_EQ(0, 682 Distance(p, Type<int8_t*>(L::Partial(0, 0).Pointer<int8_t>(p)))); 683 EXPECT_EQ( 684 0, Distance(p, Type<int32_t*>(L::Partial(0, 0).Pointer<int32_t>(p)))); 685 EXPECT_EQ(0, 686 Distance(p, Type<Int128*>(L::Partial(0, 0).Pointer<Int128>(p)))); 687 EXPECT_EQ(0, 688 Distance(p, Type<int8_t*>(L::Partial(1, 0).Pointer<int8_t>(p)))); 689 EXPECT_EQ( 690 4, Distance(p, Type<int32_t*>(L::Partial(1, 0).Pointer<int32_t>(p)))); 691 EXPECT_EQ(8, 692 Distance(p, Type<Int128*>(L::Partial(1, 0).Pointer<Int128>(p)))); 693 EXPECT_EQ(0, 694 Distance(p, Type<int8_t*>(L::Partial(5, 3).Pointer<int8_t>(p)))); 695 EXPECT_EQ( 696 8, Distance(p, Type<int32_t*>(L::Partial(5, 3).Pointer<int32_t>(p)))); 697 EXPECT_EQ(24, 698 Distance(p, Type<Int128*>(L::Partial(5, 3).Pointer<Int128>(p)))); 699 EXPECT_EQ( 700 0, Distance(p, Type<int8_t*>(L::Partial(0, 0, 0).Pointer<int8_t>(p)))); 701 EXPECT_EQ( 702 0, 703 Distance(p, Type<int32_t*>(L::Partial(0, 0, 0).Pointer<int32_t>(p)))); 704 EXPECT_EQ( 705 0, Distance(p, Type<Int128*>(L::Partial(0, 0, 0).Pointer<Int128>(p)))); 706 EXPECT_EQ( 707 0, Distance(p, Type<int8_t*>(L::Partial(1, 0, 0).Pointer<int8_t>(p)))); 708 EXPECT_EQ( 709 4, 710 Distance(p, Type<int32_t*>(L::Partial(1, 0, 0).Pointer<int32_t>(p)))); 711 EXPECT_EQ( 712 8, Distance(p, Type<Int128*>(L::Partial(1, 0, 0).Pointer<Int128>(p)))); 713 EXPECT_EQ( 714 0, Distance(p, Type<int8_t*>(L::Partial(5, 3, 1).Pointer<int8_t>(p)))); 715 EXPECT_EQ( 716 24, Distance(p, Type<Int128*>(L::Partial(5, 3, 1).Pointer<Int128>(p)))); 717 EXPECT_EQ( 718 8, 719 Distance(p, Type<int32_t*>(L::Partial(5, 3, 1).Pointer<int32_t>(p)))); 720 EXPECT_EQ(0, Distance(p, Type<int8_t*>(L(5, 3, 1).Pointer<int8_t>(p)))); 721 EXPECT_EQ(24, Distance(p, Type<Int128*>(L(5, 3, 1).Pointer<Int128>(p)))); 722 EXPECT_EQ(8, Distance(p, Type<int32_t*>(L(5, 3, 1).Pointer<int32_t>(p)))); 723 } 724 } 725 726 TEST(Layout, Pointers) { 727 alignas(max_align_t) const unsigned char p[100] = {0}; 728 using L = Layout<int8_t, int8_t, Int128>; 729 { 730 const auto x = L::Partial(); 731 EXPECT_EQ(std::make_tuple(x.Pointer<0>(p)), 732 Type<std::tuple<const int8_t*>>(x.Pointers(p))); 733 } 734 { 735 const auto x = L::Partial(1); 736 EXPECT_EQ(std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p)), 737 (Type<std::tuple<const int8_t*, const int8_t*>>(x.Pointers(p)))); 738 } 739 { 740 const auto x = L::Partial(1, 2); 741 EXPECT_EQ( 742 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)), 743 (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>( 744 x.Pointers(p)))); 745 } 746 { 747 const auto x = L::Partial(1, 2, 3); 748 EXPECT_EQ( 749 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)), 750 (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>( 751 x.Pointers(p)))); 752 } 753 { 754 const L x(1, 2, 3); 755 EXPECT_EQ( 756 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)), 757 (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>( 758 x.Pointers(p)))); 759 } 760 } 761 762 TEST(Layout, MutablePointers) { 763 alignas(max_align_t) unsigned char p[100] = {0}; 764 using L = Layout<int8_t, int8_t, Int128>; 765 { 766 const auto x = L::Partial(); 767 EXPECT_EQ(std::make_tuple(x.Pointer<0>(p)), 768 Type<std::tuple<int8_t*>>(x.Pointers(p))); 769 } 770 { 771 const auto x = L::Partial(1); 772 EXPECT_EQ(std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p)), 773 (Type<std::tuple<int8_t*, int8_t*>>(x.Pointers(p)))); 774 } 775 { 776 const auto x = L::Partial(1, 2); 777 EXPECT_EQ( 778 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)), 779 (Type<std::tuple<int8_t*, int8_t*, Int128*>>(x.Pointers(p)))); 780 } 781 { 782 const auto x = L::Partial(1, 2, 3); 783 EXPECT_EQ( 784 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)), 785 (Type<std::tuple<int8_t*, int8_t*, Int128*>>(x.Pointers(p)))); 786 } 787 { 788 const L x(1, 2, 3); 789 EXPECT_EQ( 790 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)), 791 (Type<std::tuple<int8_t*, int8_t*, Int128*>>(x.Pointers(p)))); 792 } 793 } 794 795 TEST(Layout, StaticPointers) { 796 alignas(max_align_t) const unsigned char p[100] = {0}; 797 using L = Layout<int8_t, int8_t, Int128>; 798 { 799 const auto x = L::WithStaticSizes<>::Partial(); 800 EXPECT_EQ(std::make_tuple(x.Pointer<0>(p)), 801 Type<std::tuple<const int8_t*>>(x.Pointers(p))); 802 } 803 { 804 const auto x = L::WithStaticSizes<>::Partial(1); 805 EXPECT_EQ(std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p)), 806 (Type<std::tuple<const int8_t*, const int8_t*>>(x.Pointers(p)))); 807 } 808 { 809 const auto x = L::WithStaticSizes<1>::Partial(); 810 EXPECT_EQ(std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p)), 811 (Type<std::tuple<const int8_t*, const int8_t*>>(x.Pointers(p)))); 812 } 813 { 814 const auto x = L::WithStaticSizes<>::Partial(1, 2, 3); 815 EXPECT_EQ( 816 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)), 817 (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>( 818 x.Pointers(p)))); 819 } 820 { 821 const auto x = L::WithStaticSizes<1>::Partial(2, 3); 822 EXPECT_EQ( 823 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)), 824 (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>( 825 x.Pointers(p)))); 826 } 827 { 828 const auto x = L::WithStaticSizes<1, 2>::Partial(3); 829 EXPECT_EQ( 830 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)), 831 (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>( 832 x.Pointers(p)))); 833 } 834 { 835 const auto x = L::WithStaticSizes<1, 2, 3>::Partial(); 836 EXPECT_EQ( 837 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)), 838 (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>( 839 x.Pointers(p)))); 840 } 841 { 842 const L::WithStaticSizes<1, 2, 3> x; 843 EXPECT_EQ( 844 std::make_tuple(x.Pointer<0>(p), x.Pointer<1>(p), x.Pointer<2>(p)), 845 (Type<std::tuple<const int8_t*, const int8_t*, const Int128*>>( 846 x.Pointers(p)))); 847 } 848 } 849 850 TEST(Layout, SliceByIndexSize) { 851 alignas(max_align_t) const unsigned char p[100] = {0}; 852 { 853 using L = Layout<int32_t>; 854 EXPECT_EQ(0, L::Partial(0).Slice<0>(p).size()); 855 EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size()); 856 EXPECT_EQ(3, L(3).Slice<0>(p).size()); 857 } 858 { 859 using L = Layout<int32_t, int32_t>; 860 EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size()); 861 EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size()); 862 EXPECT_EQ(5, L(3, 5).Slice<1>(p).size()); 863 } 864 { 865 using L = Layout<int8_t, int32_t, Int128>; 866 EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size()); 867 EXPECT_EQ(3, L::Partial(3, 5).Slice<0>(p).size()); 868 EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size()); 869 EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<0>(p).size()); 870 EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<1>(p).size()); 871 EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<2>(p).size()); 872 EXPECT_EQ(3, L(3, 5, 7).Slice<0>(p).size()); 873 EXPECT_EQ(5, L(3, 5, 7).Slice<1>(p).size()); 874 EXPECT_EQ(7, L(3, 5, 7).Slice<2>(p).size()); 875 } 876 } 877 878 TEST(Layout, SliceByTypeSize) { 879 alignas(max_align_t) const unsigned char p[100] = {0}; 880 { 881 using L = Layout<int32_t>; 882 EXPECT_EQ(0, L::Partial(0).Slice<int32_t>(p).size()); 883 EXPECT_EQ(3, L::Partial(3).Slice<int32_t>(p).size()); 884 EXPECT_EQ(3, L(3).Slice<int32_t>(p).size()); 885 } 886 { 887 using L = Layout<int8_t, int32_t, Int128>; 888 EXPECT_EQ(3, L::Partial(3).Slice<int8_t>(p).size()); 889 EXPECT_EQ(3, L::Partial(3, 5).Slice<int8_t>(p).size()); 890 EXPECT_EQ(5, L::Partial(3, 5).Slice<int32_t>(p).size()); 891 EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<int8_t>(p).size()); 892 EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<int32_t>(p).size()); 893 EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<Int128>(p).size()); 894 EXPECT_EQ(3, L(3, 5, 7).Slice<int8_t>(p).size()); 895 EXPECT_EQ(5, L(3, 5, 7).Slice<int32_t>(p).size()); 896 EXPECT_EQ(7, L(3, 5, 7).Slice<Int128>(p).size()); 897 } 898 } 899 TEST(Layout, MutableSliceByIndexSize) { 900 alignas(max_align_t) unsigned char p[100] = {0}; 901 { 902 using L = Layout<int32_t>; 903 EXPECT_EQ(0, L::Partial(0).Slice<0>(p).size()); 904 EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size()); 905 EXPECT_EQ(3, L(3).Slice<0>(p).size()); 906 } 907 { 908 using L = Layout<int32_t, int32_t>; 909 EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size()); 910 EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size()); 911 EXPECT_EQ(5, L(3, 5).Slice<1>(p).size()); 912 } 913 { 914 using L = Layout<int8_t, int32_t, Int128>; 915 EXPECT_EQ(3, L::Partial(3).Slice<0>(p).size()); 916 EXPECT_EQ(3, L::Partial(3, 5).Slice<0>(p).size()); 917 EXPECT_EQ(5, L::Partial(3, 5).Slice<1>(p).size()); 918 EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<0>(p).size()); 919 EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<1>(p).size()); 920 EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<2>(p).size()); 921 EXPECT_EQ(3, L(3, 5, 7).Slice<0>(p).size()); 922 EXPECT_EQ(5, L(3, 5, 7).Slice<1>(p).size()); 923 EXPECT_EQ(7, L(3, 5, 7).Slice<2>(p).size()); 924 } 925 } 926 927 TEST(Layout, MutableSliceByTypeSize) { 928 alignas(max_align_t) unsigned char p[100] = {0}; 929 { 930 using L = Layout<int32_t>; 931 EXPECT_EQ(0, L::Partial(0).Slice<int32_t>(p).size()); 932 EXPECT_EQ(3, L::Partial(3).Slice<int32_t>(p).size()); 933 EXPECT_EQ(3, L(3).Slice<int32_t>(p).size()); 934 } 935 { 936 using L = Layout<int8_t, int32_t, Int128>; 937 EXPECT_EQ(3, L::Partial(3).Slice<int8_t>(p).size()); 938 EXPECT_EQ(3, L::Partial(3, 5).Slice<int8_t>(p).size()); 939 EXPECT_EQ(5, L::Partial(3, 5).Slice<int32_t>(p).size()); 940 EXPECT_EQ(3, L::Partial(3, 5, 7).Slice<int8_t>(p).size()); 941 EXPECT_EQ(5, L::Partial(3, 5, 7).Slice<int32_t>(p).size()); 942 EXPECT_EQ(7, L::Partial(3, 5, 7).Slice<Int128>(p).size()); 943 EXPECT_EQ(3, L(3, 5, 7).Slice<int8_t>(p).size()); 944 EXPECT_EQ(5, L(3, 5, 7).Slice<int32_t>(p).size()); 945 EXPECT_EQ(7, L(3, 5, 7).Slice<Int128>(p).size()); 946 } 947 } 948 949 TEST(Layout, StaticSliceSize) { 950 alignas(max_align_t) const unsigned char cp[100] = {0}; 951 alignas(max_align_t) unsigned char p[100] = {0}; 952 using L = Layout<int8_t, int32_t, Int128>; 953 using SL = L::WithStaticSizes<3, 5>; 954 955 EXPECT_EQ(3, SL::Partial().Slice<0>(cp).size()); 956 EXPECT_EQ(3, SL::Partial().Slice<int8_t>(cp).size()); 957 EXPECT_EQ(3, SL::Partial(7).Slice<0>(cp).size()); 958 EXPECT_EQ(3, SL::Partial(7).Slice<int8_t>(cp).size()); 959 960 EXPECT_EQ(5, SL::Partial().Slice<1>(cp).size()); 961 EXPECT_EQ(5, SL::Partial().Slice<int32_t>(cp).size()); 962 EXPECT_EQ(5, SL::Partial(7).Slice<1>(cp).size()); 963 EXPECT_EQ(5, SL::Partial(7).Slice<int32_t>(cp).size()); 964 965 EXPECT_EQ(7, SL::Partial(7).Slice<2>(cp).size()); 966 EXPECT_EQ(7, SL::Partial(7).Slice<Int128>(cp).size()); 967 968 EXPECT_EQ(3, SL::Partial().Slice<0>(p).size()); 969 EXPECT_EQ(3, SL::Partial().Slice<int8_t>(p).size()); 970 EXPECT_EQ(3, SL::Partial(7).Slice<0>(p).size()); 971 EXPECT_EQ(3, SL::Partial(7).Slice<int8_t>(p).size()); 972 973 EXPECT_EQ(5, SL::Partial().Slice<1>(p).size()); 974 EXPECT_EQ(5, SL::Partial().Slice<int32_t>(p).size()); 975 EXPECT_EQ(5, SL::Partial(7).Slice<1>(p).size()); 976 EXPECT_EQ(5, SL::Partial(7).Slice<int32_t>(p).size()); 977 978 EXPECT_EQ(7, SL::Partial(7).Slice<2>(p).size()); 979 EXPECT_EQ(7, SL::Partial(7).Slice<Int128>(p).size()); 980 } 981 982 TEST(Layout, SliceByIndexData) { 983 alignas(max_align_t) const unsigned char p[100] = {0}; 984 { 985 using L = Layout<int32_t>; 986 EXPECT_EQ( 987 0, Distance( 988 p, Type<Span<const int32_t>>(L::Partial(0).Slice<0>(p)).data())); 989 EXPECT_EQ( 990 0, Distance( 991 p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data())); 992 EXPECT_EQ(0, 993 Distance(p, Type<Span<const int32_t>>(L(3).Slice<0>(p)).data())); 994 } 995 { 996 using L = Layout<int32_t, int32_t>; 997 EXPECT_EQ( 998 0, Distance( 999 p, Type<Span<const int32_t>>(L::Partial(3).Slice<0>(p)).data())); 1000 EXPECT_EQ( 1001 0, 1002 Distance( 1003 p, Type<Span<const int32_t>>(L::Partial(3, 5).Slice<0>(p)).data())); 1004 EXPECT_EQ( 1005 12, 1006 Distance( 1007 p, Type<Span<const int32_t>>(L::Partial(3, 5).Slice<1>(p)).data())); 1008 EXPECT_EQ( 1009 0, Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<0>(p)).data())); 1010 EXPECT_EQ( 1011 12, Distance(p, Type<Span<const int32_t>>(L(3, 5).Slice<1>(p)).data())); 1012 } 1013 { 1014 using L = Layout<int8_t, int32_t, Int128>; 1015 EXPECT_EQ( 1016 0, Distance( 1017 p, Type<Span<const int8_t>>(L::Partial(0).Slice<0>(p)).data())); 1018 EXPECT_EQ( 1019 0, Distance( 1020 p, Type<Span<const int8_t>>(L::Partial(1).Slice<0>(p)).data())); 1021 EXPECT_EQ( 1022 0, Distance( 1023 p, Type<Span<const int8_t>>(L::Partial(5).Slice<0>(p)).data())); 1024 EXPECT_EQ( 1025 0, 1026 Distance( 1027 p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<0>(p)).data())); 1028 EXPECT_EQ( 1029 0, 1030 Distance( 1031 p, Type<Span<const int32_t>>(L::Partial(0, 0).Slice<1>(p)).data())); 1032 EXPECT_EQ( 1033 0, 1034 Distance( 1035 p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<0>(p)).data())); 1036 EXPECT_EQ( 1037 4, 1038 Distance( 1039 p, Type<Span<const int32_t>>(L::Partial(1, 0).Slice<1>(p)).data())); 1040 EXPECT_EQ( 1041 0, 1042 Distance( 1043 p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<0>(p)).data())); 1044 EXPECT_EQ( 1045 8, 1046 Distance( 1047 p, Type<Span<const int32_t>>(L::Partial(5, 3).Slice<1>(p)).data())); 1048 EXPECT_EQ( 1049 0, 1050 Distance( 1051 p, 1052 Type<Span<const int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data())); 1053 EXPECT_EQ( 1054 0, 1055 Distance( 1056 p, 1057 Type<Span<const int32_t>>(L::Partial(0, 0, 0).Slice<1>(p)).data())); 1058 EXPECT_EQ( 1059 0, 1060 Distance( 1061 p, 1062 Type<Span<const Int128>>(L::Partial(0, 0, 0).Slice<2>(p)).data())); 1063 EXPECT_EQ( 1064 0, 1065 Distance( 1066 p, 1067 Type<Span<const int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data())); 1068 EXPECT_EQ( 1069 4, 1070 Distance( 1071 p, 1072 Type<Span<const int32_t>>(L::Partial(1, 0, 0).Slice<1>(p)).data())); 1073 EXPECT_EQ( 1074 8, 1075 Distance( 1076 p, 1077 Type<Span<const Int128>>(L::Partial(1, 0, 0).Slice<2>(p)).data())); 1078 EXPECT_EQ( 1079 0, 1080 Distance( 1081 p, 1082 Type<Span<const int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data())); 1083 EXPECT_EQ( 1084 24, 1085 Distance( 1086 p, 1087 Type<Span<const Int128>>(L::Partial(5, 3, 1).Slice<2>(p)).data())); 1088 EXPECT_EQ( 1089 8, 1090 Distance( 1091 p, 1092 Type<Span<const int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data())); 1093 EXPECT_EQ( 1094 0, 1095 Distance(p, Type<Span<const int8_t>>(L(5, 3, 1).Slice<0>(p)).data())); 1096 EXPECT_EQ( 1097 24, 1098 Distance(p, Type<Span<const Int128>>(L(5, 3, 1).Slice<2>(p)).data())); 1099 EXPECT_EQ( 1100 8, 1101 Distance(p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<1>(p)).data())); 1102 } 1103 } 1104 1105 TEST(Layout, SliceByTypeData) { 1106 alignas(max_align_t) const unsigned char p[100] = {0}; 1107 { 1108 using L = Layout<int32_t>; 1109 EXPECT_EQ( 1110 0, 1111 Distance( 1112 p, 1113 Type<Span<const int32_t>>(L::Partial(0).Slice<int32_t>(p)).data())); 1114 EXPECT_EQ( 1115 0, 1116 Distance( 1117 p, 1118 Type<Span<const int32_t>>(L::Partial(3).Slice<int32_t>(p)).data())); 1119 EXPECT_EQ( 1120 0, 1121 Distance(p, Type<Span<const int32_t>>(L(3).Slice<int32_t>(p)).data())); 1122 } 1123 { 1124 using L = Layout<int8_t, int32_t, Int128>; 1125 EXPECT_EQ( 1126 0, 1127 Distance( 1128 p, 1129 Type<Span<const int8_t>>(L::Partial(0).Slice<int8_t>(p)).data())); 1130 EXPECT_EQ( 1131 0, 1132 Distance( 1133 p, 1134 Type<Span<const int8_t>>(L::Partial(1).Slice<int8_t>(p)).data())); 1135 EXPECT_EQ( 1136 0, 1137 Distance( 1138 p, 1139 Type<Span<const int8_t>>(L::Partial(5).Slice<int8_t>(p)).data())); 1140 EXPECT_EQ( 1141 0, 1142 Distance(p, Type<Span<const int8_t>>(L::Partial(0, 0).Slice<int8_t>(p)) 1143 .data())); 1144 EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>( 1145 L::Partial(0, 0).Slice<int32_t>(p)) 1146 .data())); 1147 EXPECT_EQ( 1148 0, 1149 Distance(p, Type<Span<const int8_t>>(L::Partial(1, 0).Slice<int8_t>(p)) 1150 .data())); 1151 EXPECT_EQ(4, Distance(p, Type<Span<const int32_t>>( 1152 L::Partial(1, 0).Slice<int32_t>(p)) 1153 .data())); 1154 EXPECT_EQ( 1155 0, 1156 Distance(p, Type<Span<const int8_t>>(L::Partial(5, 3).Slice<int8_t>(p)) 1157 .data())); 1158 EXPECT_EQ(8, Distance(p, Type<Span<const int32_t>>( 1159 L::Partial(5, 3).Slice<int32_t>(p)) 1160 .data())); 1161 EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>( 1162 L::Partial(0, 0, 0).Slice<int8_t>(p)) 1163 .data())); 1164 EXPECT_EQ(0, Distance(p, Type<Span<const int32_t>>( 1165 L::Partial(0, 0, 0).Slice<int32_t>(p)) 1166 .data())); 1167 EXPECT_EQ(0, Distance(p, Type<Span<const Int128>>( 1168 L::Partial(0, 0, 0).Slice<Int128>(p)) 1169 .data())); 1170 EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>( 1171 L::Partial(1, 0, 0).Slice<int8_t>(p)) 1172 .data())); 1173 EXPECT_EQ(4, Distance(p, Type<Span<const int32_t>>( 1174 L::Partial(1, 0, 0).Slice<int32_t>(p)) 1175 .data())); 1176 EXPECT_EQ(8, Distance(p, Type<Span<const Int128>>( 1177 L::Partial(1, 0, 0).Slice<Int128>(p)) 1178 .data())); 1179 EXPECT_EQ(0, Distance(p, Type<Span<const int8_t>>( 1180 L::Partial(5, 3, 1).Slice<int8_t>(p)) 1181 .data())); 1182 EXPECT_EQ(24, Distance(p, Type<Span<const Int128>>( 1183 L::Partial(5, 3, 1).Slice<Int128>(p)) 1184 .data())); 1185 EXPECT_EQ(8, Distance(p, Type<Span<const int32_t>>( 1186 L::Partial(5, 3, 1).Slice<int32_t>(p)) 1187 .data())); 1188 EXPECT_EQ( 1189 0, 1190 Distance(p, 1191 Type<Span<const int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data())); 1192 EXPECT_EQ( 1193 24, 1194 Distance(p, 1195 Type<Span<const Int128>>(L(5, 3, 1).Slice<Int128>(p)).data())); 1196 EXPECT_EQ( 1197 8, 1198 Distance( 1199 p, Type<Span<const int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data())); 1200 } 1201 } 1202 1203 TEST(Layout, MutableSliceByIndexData) { 1204 alignas(max_align_t) unsigned char p[100] = {0}; 1205 { 1206 using L = Layout<int32_t>; 1207 EXPECT_EQ( 1208 0, Distance(p, Type<Span<int32_t>>(L::Partial(0).Slice<0>(p)).data())); 1209 EXPECT_EQ( 1210 0, Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data())); 1211 EXPECT_EQ(0, Distance(p, Type<Span<int32_t>>(L(3).Slice<0>(p)).data())); 1212 } 1213 { 1214 using L = Layout<int32_t, int32_t>; 1215 EXPECT_EQ( 1216 0, Distance(p, Type<Span<int32_t>>(L::Partial(3).Slice<0>(p)).data())); 1217 EXPECT_EQ( 1218 0, 1219 Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<0>(p)).data())); 1220 EXPECT_EQ( 1221 12, 1222 Distance(p, Type<Span<int32_t>>(L::Partial(3, 5).Slice<1>(p)).data())); 1223 EXPECT_EQ(0, Distance(p, Type<Span<int32_t>>(L(3, 5).Slice<0>(p)).data())); 1224 EXPECT_EQ(12, Distance(p, Type<Span<int32_t>>(L(3, 5).Slice<1>(p)).data())); 1225 } 1226 { 1227 using L = Layout<int8_t, int32_t, Int128>; 1228 EXPECT_EQ( 1229 0, Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<0>(p)).data())); 1230 EXPECT_EQ( 1231 0, Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<0>(p)).data())); 1232 EXPECT_EQ( 1233 0, Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<0>(p)).data())); 1234 EXPECT_EQ( 1235 0, 1236 Distance(p, Type<Span<int8_t>>(L::Partial(0, 0).Slice<0>(p)).data())); 1237 EXPECT_EQ( 1238 0, 1239 Distance(p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<1>(p)).data())); 1240 EXPECT_EQ( 1241 0, 1242 Distance(p, Type<Span<int8_t>>(L::Partial(1, 0).Slice<0>(p)).data())); 1243 EXPECT_EQ( 1244 4, 1245 Distance(p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<1>(p)).data())); 1246 EXPECT_EQ( 1247 0, 1248 Distance(p, Type<Span<int8_t>>(L::Partial(5, 3).Slice<0>(p)).data())); 1249 EXPECT_EQ( 1250 8, 1251 Distance(p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<1>(p)).data())); 1252 EXPECT_EQ( 1253 0, Distance( 1254 p, Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<0>(p)).data())); 1255 EXPECT_EQ( 1256 0, Distance( 1257 p, Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<1>(p)).data())); 1258 EXPECT_EQ( 1259 0, Distance( 1260 p, Type<Span<Int128>>(L::Partial(0, 0, 0).Slice<2>(p)).data())); 1261 EXPECT_EQ( 1262 0, Distance( 1263 p, Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<0>(p)).data())); 1264 EXPECT_EQ( 1265 4, Distance( 1266 p, Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<1>(p)).data())); 1267 EXPECT_EQ( 1268 8, Distance( 1269 p, Type<Span<Int128>>(L::Partial(1, 0, 0).Slice<2>(p)).data())); 1270 EXPECT_EQ( 1271 0, Distance( 1272 p, Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<0>(p)).data())); 1273 EXPECT_EQ( 1274 24, Distance( 1275 p, Type<Span<Int128>>(L::Partial(5, 3, 1).Slice<2>(p)).data())); 1276 EXPECT_EQ( 1277 8, Distance( 1278 p, Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<1>(p)).data())); 1279 EXPECT_EQ(0, 1280 Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<0>(p)).data())); 1281 EXPECT_EQ(24, 1282 Distance(p, Type<Span<Int128>>(L(5, 3, 1).Slice<2>(p)).data())); 1283 EXPECT_EQ(8, 1284 Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<1>(p)).data())); 1285 } 1286 } 1287 1288 TEST(Layout, MutableSliceByTypeData) { 1289 alignas(max_align_t) unsigned char p[100] = {0}; 1290 { 1291 using L = Layout<int32_t>; 1292 EXPECT_EQ( 1293 0, Distance( 1294 p, Type<Span<int32_t>>(L::Partial(0).Slice<int32_t>(p)).data())); 1295 EXPECT_EQ( 1296 0, Distance( 1297 p, Type<Span<int32_t>>(L::Partial(3).Slice<int32_t>(p)).data())); 1298 EXPECT_EQ(0, 1299 Distance(p, Type<Span<int32_t>>(L(3).Slice<int32_t>(p)).data())); 1300 } 1301 { 1302 using L = Layout<int8_t, int32_t, Int128>; 1303 EXPECT_EQ( 1304 0, 1305 Distance(p, Type<Span<int8_t>>(L::Partial(0).Slice<int8_t>(p)).data())); 1306 EXPECT_EQ( 1307 0, 1308 Distance(p, Type<Span<int8_t>>(L::Partial(1).Slice<int8_t>(p)).data())); 1309 EXPECT_EQ( 1310 0, 1311 Distance(p, Type<Span<int8_t>>(L::Partial(5).Slice<int8_t>(p)).data())); 1312 EXPECT_EQ( 1313 0, 1314 Distance(p, 1315 Type<Span<int8_t>>(L::Partial(0, 0).Slice<int8_t>(p)).data())); 1316 EXPECT_EQ( 1317 0, 1318 Distance( 1319 p, Type<Span<int32_t>>(L::Partial(0, 0).Slice<int32_t>(p)).data())); 1320 EXPECT_EQ( 1321 0, 1322 Distance(p, 1323 Type<Span<int8_t>>(L::Partial(1, 0).Slice<int8_t>(p)).data())); 1324 EXPECT_EQ( 1325 4, 1326 Distance( 1327 p, Type<Span<int32_t>>(L::Partial(1, 0).Slice<int32_t>(p)).data())); 1328 EXPECT_EQ( 1329 0, 1330 Distance(p, 1331 Type<Span<int8_t>>(L::Partial(5, 3).Slice<int8_t>(p)).data())); 1332 EXPECT_EQ( 1333 8, 1334 Distance( 1335 p, Type<Span<int32_t>>(L::Partial(5, 3).Slice<int32_t>(p)).data())); 1336 EXPECT_EQ( 1337 0, 1338 Distance( 1339 p, 1340 Type<Span<int8_t>>(L::Partial(0, 0, 0).Slice<int8_t>(p)).data())); 1341 EXPECT_EQ( 1342 0, 1343 Distance( 1344 p, 1345 Type<Span<int32_t>>(L::Partial(0, 0, 0).Slice<int32_t>(p)).data())); 1346 EXPECT_EQ( 1347 0, 1348 Distance( 1349 p, 1350 Type<Span<Int128>>(L::Partial(0, 0, 0).Slice<Int128>(p)).data())); 1351 EXPECT_EQ( 1352 0, 1353 Distance( 1354 p, 1355 Type<Span<int8_t>>(L::Partial(1, 0, 0).Slice<int8_t>(p)).data())); 1356 EXPECT_EQ( 1357 4, 1358 Distance( 1359 p, 1360 Type<Span<int32_t>>(L::Partial(1, 0, 0).Slice<int32_t>(p)).data())); 1361 EXPECT_EQ( 1362 8, 1363 Distance( 1364 p, 1365 Type<Span<Int128>>(L::Partial(1, 0, 0).Slice<Int128>(p)).data())); 1366 EXPECT_EQ( 1367 0, 1368 Distance( 1369 p, 1370 Type<Span<int8_t>>(L::Partial(5, 3, 1).Slice<int8_t>(p)).data())); 1371 EXPECT_EQ( 1372 24, 1373 Distance( 1374 p, 1375 Type<Span<Int128>>(L::Partial(5, 3, 1).Slice<Int128>(p)).data())); 1376 EXPECT_EQ( 1377 8, 1378 Distance( 1379 p, 1380 Type<Span<int32_t>>(L::Partial(5, 3, 1).Slice<int32_t>(p)).data())); 1381 EXPECT_EQ( 1382 0, Distance(p, Type<Span<int8_t>>(L(5, 3, 1).Slice<int8_t>(p)).data())); 1383 EXPECT_EQ( 1384 24, 1385 Distance(p, Type<Span<Int128>>(L(5, 3, 1).Slice<Int128>(p)).data())); 1386 EXPECT_EQ( 1387 8, 1388 Distance(p, Type<Span<int32_t>>(L(5, 3, 1).Slice<int32_t>(p)).data())); 1389 } 1390 } 1391 1392 TEST(Layout, StaticSliceData) { 1393 alignas(max_align_t) const unsigned char cp[100] = {0}; 1394 alignas(max_align_t) unsigned char p[100] = {0}; 1395 using L = Layout<int8_t, int32_t, Int128>; 1396 using SL = L::WithStaticSizes<3, 5>; 1397 1398 EXPECT_EQ(0, Distance(cp, SL::Partial().Slice<0>(cp).data())); 1399 EXPECT_EQ(0, Distance(cp, SL::Partial().Slice<int8_t>(cp).data())); 1400 EXPECT_EQ(0, Distance(cp, SL::Partial(7).Slice<0>(cp).data())); 1401 EXPECT_EQ(0, Distance(cp, SL::Partial(7).Slice<int8_t>(cp).data())); 1402 1403 EXPECT_EQ(4, Distance(cp, SL::Partial().Slice<1>(cp).data())); 1404 EXPECT_EQ(4, Distance(cp, SL::Partial().Slice<int32_t>(cp).data())); 1405 EXPECT_EQ(4, Distance(cp, SL::Partial(7).Slice<1>(cp).data())); 1406 EXPECT_EQ(4, Distance(cp, SL::Partial(7).Slice<int32_t>(cp).data())); 1407 1408 EXPECT_EQ(24, Distance(cp, SL::Partial(7).Slice<2>(cp).data())); 1409 EXPECT_EQ(24, Distance(cp, SL::Partial(7).Slice<Int128>(cp).data())); 1410 1411 EXPECT_EQ(0, Distance(p, SL::Partial().Slice<0>(p).data())); 1412 EXPECT_EQ(0, Distance(p, SL::Partial().Slice<int8_t>(p).data())); 1413 EXPECT_EQ(0, Distance(p, SL::Partial(7).Slice<0>(p).data())); 1414 EXPECT_EQ(0, Distance(p, SL::Partial(7).Slice<int8_t>(p).data())); 1415 1416 EXPECT_EQ(4, Distance(p, SL::Partial().Slice<1>(p).data())); 1417 EXPECT_EQ(4, Distance(p, SL::Partial().Slice<int32_t>(p).data())); 1418 EXPECT_EQ(4, Distance(p, SL::Partial(7).Slice<1>(p).data())); 1419 EXPECT_EQ(4, Distance(p, SL::Partial(7).Slice<int32_t>(p).data())); 1420 1421 EXPECT_EQ(24, Distance(p, SL::Partial(7).Slice<2>(p).data())); 1422 EXPECT_EQ(24, Distance(p, SL::Partial(7).Slice<Int128>(p).data())); 1423 } 1424 1425 MATCHER_P(IsSameSlice, slice, "") { 1426 return arg.size() == slice.size() && arg.data() == slice.data(); 1427 } 1428 1429 template <typename... M> 1430 class TupleMatcher { 1431 public: 1432 explicit TupleMatcher(M... matchers) : matchers_(std::move(matchers)...) {} 1433 1434 template <typename Tuple> 1435 bool MatchAndExplain(const Tuple& p, 1436 testing::MatchResultListener* /* listener */) const { 1437 static_assert(std::tuple_size<Tuple>::value == sizeof...(M), ""); 1438 return MatchAndExplainImpl( 1439 p, absl::make_index_sequence<std::tuple_size<Tuple>::value>{}); 1440 } 1441 1442 // For the matcher concept. Left empty as we don't really need the diagnostics 1443 // right now. 1444 void DescribeTo(::std::ostream* os) const {} 1445 void DescribeNegationTo(::std::ostream* os) const {} 1446 1447 private: 1448 template <typename Tuple, size_t... Is> 1449 bool MatchAndExplainImpl(const Tuple& p, absl::index_sequence<Is...>) const { 1450 // Using std::min as a simple variadic "and". 1451 return std::min( 1452 {true, testing::SafeMatcherCast< 1453 const typename std::tuple_element<Is, Tuple>::type&>( 1454 std::get<Is>(matchers_)) 1455 .Matches(std::get<Is>(p))...}); 1456 } 1457 1458 std::tuple<M...> matchers_; 1459 }; 1460 1461 template <typename... M> 1462 testing::PolymorphicMatcher<TupleMatcher<M...>> Tuple(M... matchers) { 1463 return testing::MakePolymorphicMatcher( 1464 TupleMatcher<M...>(std::move(matchers)...)); 1465 } 1466 1467 TEST(Layout, Slices) { 1468 alignas(max_align_t) const unsigned char p[100] = {0}; 1469 using L = Layout<int8_t, int8_t, Int128>; 1470 { 1471 const auto x = L::Partial(); 1472 EXPECT_THAT(Type<std::tuple<>>(x.Slices(p)), Tuple()); 1473 } 1474 { 1475 const auto x = L::Partial(1); 1476 EXPECT_THAT(Type<std::tuple<Span<const int8_t>>>(x.Slices(p)), 1477 Tuple(IsSameSlice(x.Slice<0>(p)))); 1478 } 1479 { 1480 const auto x = L::Partial(1, 2); 1481 EXPECT_THAT( 1482 (Type<std::tuple<Span<const int8_t>, Span<const int8_t>>>(x.Slices(p))), 1483 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)))); 1484 } 1485 { 1486 const auto x = L::Partial(1, 2, 3); 1487 EXPECT_THAT((Type<std::tuple<Span<const int8_t>, Span<const int8_t>, 1488 Span<const Int128>>>(x.Slices(p))), 1489 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)), 1490 IsSameSlice(x.Slice<2>(p)))); 1491 } 1492 { 1493 const L x(1, 2, 3); 1494 EXPECT_THAT((Type<std::tuple<Span<const int8_t>, Span<const int8_t>, 1495 Span<const Int128>>>(x.Slices(p))), 1496 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)), 1497 IsSameSlice(x.Slice<2>(p)))); 1498 } 1499 } 1500 1501 TEST(Layout, MutableSlices) { 1502 alignas(max_align_t) unsigned char p[100] = {0}; 1503 using L = Layout<int8_t, int8_t, Int128>; 1504 { 1505 const auto x = L::Partial(); 1506 EXPECT_THAT(Type<std::tuple<>>(x.Slices(p)), Tuple()); 1507 } 1508 { 1509 const auto x = L::Partial(1); 1510 EXPECT_THAT(Type<std::tuple<Span<int8_t>>>(x.Slices(p)), 1511 Tuple(IsSameSlice(x.Slice<0>(p)))); 1512 } 1513 { 1514 const auto x = L::Partial(1, 2); 1515 EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>>>(x.Slices(p))), 1516 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)))); 1517 } 1518 { 1519 const auto x = L::Partial(1, 2, 3); 1520 EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>( 1521 x.Slices(p))), 1522 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)), 1523 IsSameSlice(x.Slice<2>(p)))); 1524 } 1525 { 1526 const L x(1, 2, 3); 1527 EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>( 1528 x.Slices(p))), 1529 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)), 1530 IsSameSlice(x.Slice<2>(p)))); 1531 } 1532 } 1533 1534 TEST(Layout, StaticSlices) { 1535 alignas(max_align_t) const unsigned char cp[100] = {0}; 1536 alignas(max_align_t) unsigned char p[100] = {0}; 1537 using SL = Layout<int8_t, int8_t, Int128>::WithStaticSizes<1, 2>; 1538 { 1539 const auto x = SL::Partial(); 1540 EXPECT_THAT( 1541 (Type<std::tuple<Span<const int8_t>, Span<const int8_t>>>( 1542 x.Slices(cp))), 1543 Tuple(IsSameSlice(x.Slice<0>(cp)), IsSameSlice(x.Slice<1>(cp)))); 1544 EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>>>(x.Slices(p))), 1545 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)))); 1546 } 1547 { 1548 const auto x = SL::Partial(3); 1549 EXPECT_THAT((Type<std::tuple<Span<const int8_t>, Span<const int8_t>, 1550 Span<const Int128>>>(x.Slices(cp))), 1551 Tuple(IsSameSlice(x.Slice<0>(cp)), IsSameSlice(x.Slice<1>(cp)), 1552 IsSameSlice(x.Slice<2>(cp)))); 1553 EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>( 1554 x.Slices(p))), 1555 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)), 1556 IsSameSlice(x.Slice<2>(p)))); 1557 } 1558 { 1559 const SL x(3); 1560 EXPECT_THAT((Type<std::tuple<Span<const int8_t>, Span<const int8_t>, 1561 Span<const Int128>>>(x.Slices(cp))), 1562 Tuple(IsSameSlice(x.Slice<0>(cp)), IsSameSlice(x.Slice<1>(cp)), 1563 IsSameSlice(x.Slice<2>(cp)))); 1564 EXPECT_THAT((Type<std::tuple<Span<int8_t>, Span<int8_t>, Span<Int128>>>( 1565 x.Slices(p))), 1566 Tuple(IsSameSlice(x.Slice<0>(p)), IsSameSlice(x.Slice<1>(p)), 1567 IsSameSlice(x.Slice<2>(p)))); 1568 } 1569 } 1570 1571 TEST(Layout, UnalignedTypes) { 1572 constexpr Layout<unsigned char, unsigned char, unsigned char> x(1, 2, 3); 1573 alignas(max_align_t) unsigned char p[x.AllocSize() + 1]; 1574 EXPECT_THAT(x.Pointers(p + 1), Tuple(p + 1, p + 2, p + 4)); 1575 } 1576 1577 TEST(Layout, CustomAlignment) { 1578 constexpr Layout<unsigned char, Aligned<unsigned char, 8>> x(1, 2); 1579 alignas(max_align_t) unsigned char p[x.AllocSize()]; 1580 EXPECT_EQ(10, x.AllocSize()); 1581 EXPECT_THAT(x.Pointers(p), Tuple(p + 0, p + 8)); 1582 } 1583 1584 TEST(Layout, OverAligned) { 1585 constexpr size_t M = alignof(max_align_t); 1586 constexpr Layout<unsigned char, Aligned<unsigned char, 2 * M>> x(1, 3); 1587 #ifdef __GNUC__ 1588 // Using __attribute__ ((aligned ())) instead of alignas to bypass a gcc bug: 1589 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89357 1590 __attribute__((aligned(2 * M))) unsigned char p[x.AllocSize()]; 1591 #else 1592 alignas(2 * M) unsigned char p[x.AllocSize()]; 1593 #endif 1594 EXPECT_EQ(2 * M + 3, x.AllocSize()); 1595 EXPECT_THAT(x.Pointers(p), Tuple(p + 0, p + 2 * M)); 1596 } 1597 1598 TEST(Layout, Alignment) { 1599 static_assert(Layout<int8_t>::Alignment() == 1, ""); 1600 static_assert(Layout<int32_t>::Alignment() == 4, ""); 1601 static_assert(Layout<Int64>::Alignment() == 8, ""); 1602 static_assert(Layout<Aligned<int8_t, 64>>::Alignment() == 64, ""); 1603 static_assert(Layout<int8_t, int32_t, Int64>::Alignment() == 8, ""); 1604 static_assert(Layout<int8_t, Int64, int32_t>::Alignment() == 8, ""); 1605 static_assert(Layout<int32_t, int8_t, Int64>::Alignment() == 8, ""); 1606 static_assert(Layout<int32_t, Int64, int8_t>::Alignment() == 8, ""); 1607 static_assert(Layout<Int64, int8_t, int32_t>::Alignment() == 8, ""); 1608 static_assert(Layout<Int64, int32_t, int8_t>::Alignment() == 8, ""); 1609 static_assert(Layout<Int64, int32_t, int8_t>::Alignment() == 8, ""); 1610 static_assert( 1611 Layout<Aligned<int8_t, 64>>::WithStaticSizes<>::Alignment() == 64, ""); 1612 static_assert( 1613 Layout<Aligned<int8_t, 64>>::WithStaticSizes<2>::Alignment() == 64, ""); 1614 } 1615 1616 TEST(Layout, StaticAlignment) { 1617 static_assert(Layout<int8_t>::WithStaticSizes<>::Alignment() == 1, ""); 1618 static_assert(Layout<int8_t>::WithStaticSizes<0>::Alignment() == 1, ""); 1619 static_assert(Layout<int8_t>::WithStaticSizes<7>::Alignment() == 1, ""); 1620 static_assert(Layout<int32_t>::WithStaticSizes<>::Alignment() == 4, ""); 1621 static_assert(Layout<int32_t>::WithStaticSizes<0>::Alignment() == 4, ""); 1622 static_assert(Layout<int32_t>::WithStaticSizes<3>::Alignment() == 4, ""); 1623 static_assert( 1624 Layout<Aligned<int8_t, 64>>::WithStaticSizes<>::Alignment() == 64, ""); 1625 static_assert( 1626 Layout<Aligned<int8_t, 64>>::WithStaticSizes<0>::Alignment() == 64, ""); 1627 static_assert( 1628 Layout<Aligned<int8_t, 64>>::WithStaticSizes<2>::Alignment() == 64, ""); 1629 static_assert( 1630 Layout<int32_t, Int64, int8_t>::WithStaticSizes<>::Alignment() == 8, ""); 1631 static_assert( 1632 Layout<int32_t, Int64, int8_t>::WithStaticSizes<0, 0, 0>::Alignment() == 1633 8, 1634 ""); 1635 static_assert( 1636 Layout<int32_t, Int64, int8_t>::WithStaticSizes<1, 1, 1>::Alignment() == 1637 8, 1638 ""); 1639 } 1640 1641 TEST(Layout, ConstexprPartial) { 1642 constexpr size_t M = alignof(max_align_t); 1643 constexpr Layout<unsigned char, Aligned<unsigned char, 2 * M>> x(1, 3); 1644 static_assert(x.Partial(1).template Offset<1>() == 2 * M, ""); 1645 } 1646 1647 TEST(Layout, StaticConstexpr) { 1648 constexpr size_t M = alignof(max_align_t); 1649 using L = Layout<unsigned char, Aligned<unsigned char, 2 * M>>; 1650 using SL = L::WithStaticSizes<1, 3>; 1651 constexpr SL x; 1652 static_assert(x.Offset<1>() == 2 * M, ""); 1653 } 1654 1655 // [from, to) 1656 struct Region { 1657 size_t from; 1658 size_t to; 1659 }; 1660 1661 void ExpectRegionPoisoned(const unsigned char* p, size_t n, bool poisoned) { 1662 #ifdef ABSL_HAVE_ADDRESS_SANITIZER 1663 for (size_t i = 0; i != n; ++i) { 1664 EXPECT_EQ(poisoned, __asan_address_is_poisoned(p + i)); 1665 } 1666 #endif 1667 } 1668 1669 template <size_t N> 1670 void ExpectPoisoned(const unsigned char (&buf)[N], 1671 std::initializer_list<Region> reg) { 1672 size_t prev = 0; 1673 for (const Region& r : reg) { 1674 ExpectRegionPoisoned(buf + prev, r.from - prev, false); 1675 ExpectRegionPoisoned(buf + r.from, r.to - r.from, true); 1676 prev = r.to; 1677 } 1678 ExpectRegionPoisoned(buf + prev, N - prev, false); 1679 } 1680 1681 TEST(Layout, PoisonPadding) { 1682 using L = Layout<int8_t, Int64, int32_t, Int128>; 1683 1684 constexpr size_t n = L::Partial(1, 2, 3, 4).AllocSize(); 1685 { 1686 constexpr auto x = L::Partial(); 1687 alignas(max_align_t) const unsigned char c[n] = {}; 1688 x.PoisonPadding(c); 1689 EXPECT_EQ(x.Slices(c), x.Slices(c)); 1690 ExpectPoisoned(c, {}); 1691 } 1692 { 1693 constexpr auto x = L::Partial(1); 1694 alignas(max_align_t) const unsigned char c[n] = {}; 1695 x.PoisonPadding(c); 1696 EXPECT_EQ(x.Slices(c), x.Slices(c)); 1697 ExpectPoisoned(c, {{1, 8}}); 1698 } 1699 { 1700 constexpr auto x = L::Partial(1, 2); 1701 alignas(max_align_t) const unsigned char c[n] = {}; 1702 x.PoisonPadding(c); 1703 EXPECT_EQ(x.Slices(c), x.Slices(c)); 1704 ExpectPoisoned(c, {{1, 8}}); 1705 } 1706 { 1707 constexpr auto x = L::Partial(1, 2, 3); 1708 alignas(max_align_t) const unsigned char c[n] = {}; 1709 x.PoisonPadding(c); 1710 EXPECT_EQ(x.Slices(c), x.Slices(c)); 1711 ExpectPoisoned(c, {{1, 8}, {36, 40}}); 1712 } 1713 { 1714 constexpr auto x = L::Partial(1, 2, 3, 4); 1715 alignas(max_align_t) const unsigned char c[n] = {}; 1716 x.PoisonPadding(c); 1717 EXPECT_EQ(x.Slices(c), x.Slices(c)); 1718 ExpectPoisoned(c, {{1, 8}, {36, 40}}); 1719 } 1720 { 1721 constexpr L x(1, 2, 3, 4); 1722 alignas(max_align_t) const unsigned char c[n] = {}; 1723 x.PoisonPadding(c); 1724 EXPECT_EQ(x.Slices(c), x.Slices(c)); 1725 ExpectPoisoned(c, {{1, 8}, {36, 40}}); 1726 } 1727 } 1728 1729 TEST(Layout, StaticPoisonPadding) { 1730 using L = Layout<int8_t, Int64, int32_t, Int128>; 1731 using SL = L::WithStaticSizes<1, 2>; 1732 1733 constexpr size_t n = L::Partial(1, 2, 3, 4).AllocSize(); 1734 { 1735 constexpr auto x = SL::Partial(); 1736 alignas(max_align_t) const unsigned char c[n] = {}; 1737 x.PoisonPadding(c); 1738 EXPECT_EQ(x.Slices(c), x.Slices(c)); 1739 ExpectPoisoned(c, {{1, 8}}); 1740 } 1741 { 1742 constexpr auto x = SL::Partial(3); 1743 alignas(max_align_t) const unsigned char c[n] = {}; 1744 x.PoisonPadding(c); 1745 EXPECT_EQ(x.Slices(c), x.Slices(c)); 1746 ExpectPoisoned(c, {{1, 8}, {36, 40}}); 1747 } 1748 { 1749 constexpr auto x = SL::Partial(3, 4); 1750 alignas(max_align_t) const unsigned char c[n] = {}; 1751 x.PoisonPadding(c); 1752 EXPECT_EQ(x.Slices(c), x.Slices(c)); 1753 ExpectPoisoned(c, {{1, 8}, {36, 40}}); 1754 } 1755 { 1756 constexpr SL x(3, 4); 1757 alignas(max_align_t) const unsigned char c[n] = {}; 1758 x.PoisonPadding(c); 1759 EXPECT_EQ(x.Slices(c), x.Slices(c)); 1760 ExpectPoisoned(c, {{1, 8}, {36, 40}}); 1761 } 1762 } 1763 1764 TEST(Layout, DebugString) { 1765 { 1766 constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(); 1767 EXPECT_EQ("@0<signed char>(1)", x.DebugString()); 1768 } 1769 { 1770 constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1); 1771 EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)", x.DebugString()); 1772 } 1773 { 1774 constexpr auto x = Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2); 1775 EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)", 1776 x.DebugString()); 1777 } 1778 { 1779 constexpr auto x = 1780 Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3); 1781 EXPECT_EQ( 1782 "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; " 1783 "@16" + 1784 Int128::Name() + "(16)", 1785 x.DebugString()); 1786 } 1787 { 1788 constexpr auto x = 1789 Layout<int8_t, int32_t, int8_t, Int128>::Partial(1, 2, 3, 4); 1790 EXPECT_EQ( 1791 "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; " 1792 "@16" + 1793 Int128::Name() + "(16)[4]", 1794 x.DebugString()); 1795 } 1796 { 1797 constexpr Layout<int8_t, int32_t, int8_t, Int128> x(1, 2, 3, 4); 1798 EXPECT_EQ( 1799 "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; " 1800 "@16" + 1801 Int128::Name() + "(16)[4]", 1802 x.DebugString()); 1803 } 1804 } 1805 1806 TEST(Layout, StaticDebugString) { 1807 { 1808 constexpr auto x = 1809 Layout<int8_t, int32_t, int8_t, Int128>::WithStaticSizes<>::Partial(); 1810 EXPECT_EQ("@0<signed char>(1)", x.DebugString()); 1811 } 1812 { 1813 constexpr auto x = 1814 Layout<int8_t, int32_t, int8_t, Int128>::WithStaticSizes<>::Partial(1); 1815 EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)", x.DebugString()); 1816 } 1817 { 1818 constexpr auto x = 1819 Layout<int8_t, int32_t, int8_t, Int128>::WithStaticSizes<1>::Partial(); 1820 EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)", x.DebugString()); 1821 } 1822 { 1823 constexpr auto x = 1824 Layout<int8_t, int32_t, int8_t, Int128>::WithStaticSizes<>::Partial(1, 1825 2); 1826 EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)", 1827 x.DebugString()); 1828 } 1829 { 1830 constexpr auto x = 1831 Layout<int8_t, int32_t, int8_t, Int128>::WithStaticSizes<1>::Partial(2); 1832 EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)", 1833 x.DebugString()); 1834 } 1835 { 1836 constexpr auto x = Layout<int8_t, int32_t, int8_t, 1837 Int128>::WithStaticSizes<1, 2>::Partial(); 1838 EXPECT_EQ("@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)", 1839 x.DebugString()); 1840 } 1841 { 1842 constexpr auto x = Layout<int8_t, int32_t, int8_t, 1843 Int128>::WithStaticSizes<1, 2, 3, 4>::Partial(); 1844 EXPECT_EQ( 1845 "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; " 1846 "@16" + 1847 Int128::Name() + "(16)[4]", 1848 x.DebugString()); 1849 } 1850 { 1851 constexpr Layout<int8_t, int32_t, int8_t, Int128>::WithStaticSizes<1, 2, 3, 1852 4> 1853 x; 1854 EXPECT_EQ( 1855 "@0<signed char>(1)[1]; @4<int>(4)[2]; @12<signed char>(1)[3]; " 1856 "@16" + 1857 Int128::Name() + "(16)[4]", 1858 x.DebugString()); 1859 } 1860 } 1861 1862 TEST(Layout, CharTypes) { 1863 constexpr Layout<int32_t> x(1); 1864 alignas(max_align_t) char c[x.AllocSize()] = {}; 1865 alignas(max_align_t) unsigned char uc[x.AllocSize()] = {}; 1866 alignas(max_align_t) signed char sc[x.AllocSize()] = {}; 1867 alignas(max_align_t) const char cc[x.AllocSize()] = {}; 1868 alignas(max_align_t) const unsigned char cuc[x.AllocSize()] = {}; 1869 alignas(max_align_t) const signed char csc[x.AllocSize()] = {}; 1870 1871 Type<int32_t*>(x.Pointer<0>(c)); 1872 Type<int32_t*>(x.Pointer<0>(uc)); 1873 Type<int32_t*>(x.Pointer<0>(sc)); 1874 Type<const int32_t*>(x.Pointer<0>(cc)); 1875 Type<const int32_t*>(x.Pointer<0>(cuc)); 1876 Type<const int32_t*>(x.Pointer<0>(csc)); 1877 1878 Type<int32_t*>(x.Pointer<int32_t>(c)); 1879 Type<int32_t*>(x.Pointer<int32_t>(uc)); 1880 Type<int32_t*>(x.Pointer<int32_t>(sc)); 1881 Type<const int32_t*>(x.Pointer<int32_t>(cc)); 1882 Type<const int32_t*>(x.Pointer<int32_t>(cuc)); 1883 Type<const int32_t*>(x.Pointer<int32_t>(csc)); 1884 1885 Type<std::tuple<int32_t*>>(x.Pointers(c)); 1886 Type<std::tuple<int32_t*>>(x.Pointers(uc)); 1887 Type<std::tuple<int32_t*>>(x.Pointers(sc)); 1888 Type<std::tuple<const int32_t*>>(x.Pointers(cc)); 1889 Type<std::tuple<const int32_t*>>(x.Pointers(cuc)); 1890 Type<std::tuple<const int32_t*>>(x.Pointers(csc)); 1891 1892 Type<Span<int32_t>>(x.Slice<0>(c)); 1893 Type<Span<int32_t>>(x.Slice<0>(uc)); 1894 Type<Span<int32_t>>(x.Slice<0>(sc)); 1895 Type<Span<const int32_t>>(x.Slice<0>(cc)); 1896 Type<Span<const int32_t>>(x.Slice<0>(cuc)); 1897 Type<Span<const int32_t>>(x.Slice<0>(csc)); 1898 1899 Type<std::tuple<Span<int32_t>>>(x.Slices(c)); 1900 Type<std::tuple<Span<int32_t>>>(x.Slices(uc)); 1901 Type<std::tuple<Span<int32_t>>>(x.Slices(sc)); 1902 Type<std::tuple<Span<const int32_t>>>(x.Slices(cc)); 1903 Type<std::tuple<Span<const int32_t>>>(x.Slices(cuc)); 1904 Type<std::tuple<Span<const int32_t>>>(x.Slices(csc)); 1905 } 1906 1907 TEST(Layout, ConstElementType) { 1908 constexpr Layout<const int32_t> x(1); 1909 alignas(int32_t) char c[x.AllocSize()] = {}; 1910 const char* cc = c; 1911 const int32_t* p = reinterpret_cast<const int32_t*>(cc); 1912 1913 EXPECT_EQ(alignof(int32_t), x.Alignment()); 1914 1915 EXPECT_EQ(0, x.Offset<0>()); 1916 EXPECT_EQ(0, x.Offset<const int32_t>()); 1917 1918 EXPECT_THAT(x.Offsets(), ElementsAre(0)); 1919 1920 EXPECT_EQ(1, x.Size<0>()); 1921 EXPECT_EQ(1, x.Size<const int32_t>()); 1922 1923 EXPECT_THAT(x.Sizes(), ElementsAre(1)); 1924 1925 EXPECT_EQ(sizeof(int32_t), x.AllocSize()); 1926 1927 EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<0>(c))); 1928 EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<0>(cc))); 1929 1930 EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<const int32_t>(c))); 1931 EXPECT_EQ(p, Type<const int32_t*>(x.Pointer<const int32_t>(cc))); 1932 1933 EXPECT_THAT(Type<std::tuple<const int32_t*>>(x.Pointers(c)), Tuple(p)); 1934 EXPECT_THAT(Type<std::tuple<const int32_t*>>(x.Pointers(cc)), Tuple(p)); 1935 1936 EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<0>(c)), 1937 IsSameSlice(Span<const int32_t>(p, 1))); 1938 EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<0>(cc)), 1939 IsSameSlice(Span<const int32_t>(p, 1))); 1940 1941 EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<const int32_t>(c)), 1942 IsSameSlice(Span<const int32_t>(p, 1))); 1943 EXPECT_THAT(Type<Span<const int32_t>>(x.Slice<const int32_t>(cc)), 1944 IsSameSlice(Span<const int32_t>(p, 1))); 1945 1946 EXPECT_THAT(Type<std::tuple<Span<const int32_t>>>(x.Slices(c)), 1947 Tuple(IsSameSlice(Span<const int32_t>(p, 1)))); 1948 EXPECT_THAT(Type<std::tuple<Span<const int32_t>>>(x.Slices(cc)), 1949 Tuple(IsSameSlice(Span<const int32_t>(p, 1)))); 1950 } 1951 1952 namespace example { 1953 1954 // Immutable move-only string with sizeof equal to sizeof(void*). The string 1955 // size and the characters are kept in the same heap allocation. 1956 class CompactString { 1957 public: 1958 CompactString(const char* s = "") { // NOLINT 1959 const size_t size = strlen(s); 1960 // size_t[1], followed by char[size + 1]. 1961 // This statement doesn't allocate memory. 1962 const L layout(1, size + 1); 1963 // AllocSize() tells us how much memory we need to allocate for all our 1964 // data. 1965 p_.reset(new unsigned char[layout.AllocSize()]); 1966 // If running under ASAN, mark the padding bytes, if any, to catch memory 1967 // errors. 1968 layout.PoisonPadding(p_.get()); 1969 // Store the size in the allocation. 1970 // Pointer<size_t>() is a synonym for Pointer<0>(). 1971 *layout.Pointer<size_t>(p_.get()) = size; 1972 // Store the characters in the allocation. 1973 memcpy(layout.Pointer<char>(p_.get()), s, size + 1); 1974 } 1975 1976 size_t size() const { 1977 // Equivalent to reinterpret_cast<size_t&>(*p). 1978 return *L::Partial().Pointer<size_t>(p_.get()); 1979 } 1980 1981 const char* c_str() const { 1982 // Equivalent to reinterpret_cast<char*>(p.get() + sizeof(size_t)). 1983 // The argument in Partial(1) specifies that we have size_t[1] in front of 1984 // the characters. 1985 return L::Partial(1).Pointer<char>(p_.get()); 1986 } 1987 1988 private: 1989 // Our heap allocation contains a size_t followed by an array of chars. 1990 using L = Layout<size_t, char>; 1991 std::unique_ptr<unsigned char[]> p_; 1992 }; 1993 1994 TEST(CompactString, Works) { 1995 CompactString s = "hello"; 1996 EXPECT_EQ(5, s.size()); 1997 EXPECT_STREQ("hello", s.c_str()); 1998 } 1999 2000 // Same as the previous CompactString example, except we set the first array 2001 // size to 1 statically, since we know it is always 1. This allows us to compute 2002 // the offset of the character array at compile time. 2003 class StaticCompactString { 2004 public: 2005 StaticCompactString(const char* s = "") { // NOLINT 2006 const size_t size = strlen(s); 2007 const SL layout(size + 1); 2008 p_.reset(new unsigned char[layout.AllocSize()]); 2009 layout.PoisonPadding(p_.get()); 2010 *layout.Pointer<size_t>(p_.get()) = size; 2011 memcpy(layout.Pointer<char>(p_.get()), s, size + 1); 2012 } 2013 2014 size_t size() const { return *SL::Partial().Pointer<size_t>(p_.get()); } 2015 2016 const char* c_str() const { return SL::Partial().Pointer<char>(p_.get()); } 2017 2018 private: 2019 using SL = Layout<size_t, char>::WithStaticSizes<1>; 2020 std::unique_ptr<unsigned char[]> p_; 2021 }; 2022 2023 TEST(StaticCompactString, Works) { 2024 StaticCompactString s = "hello"; 2025 EXPECT_EQ(5, s.size()); 2026 EXPECT_STREQ("hello", s.c_str()); 2027 } 2028 2029 } // namespace example 2030 2031 } // namespace 2032 } // namespace container_internal 2033 ABSL_NAMESPACE_END 2034 } // namespace absl