OpenKalman
no_unique_address.hpp
1 //@HEADER
2 // ************************************************************************
3 //
4 // Kokkos v. 4.0
5 // Copyright (2022) National Technology & Engineering
6 // Solutions of Sandia, LLC (NTESS).
7 //
8 // Under the terms of Contract DE-NA0003525 with NTESS,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions.
12 // See https://kokkos.org/LICENSE for license information.
13 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
14 //
15 //@HEADER
16 #pragma once
17 
18 #include "macros.hpp"
19 #include "trait_backports.hpp"
20 
21 namespace std {
22 namespace experimental {
23 namespace detail {
24 
25 //==============================================================================
26 
27 template <class _T, size_t _Disambiguator = 0, class _Enable = void>
29  using __stored_type = _T;
30  _T __v;
31  MDSPAN_FORCE_INLINE_FUNCTION constexpr _T const &__ref() const noexcept {
32  return __v;
33  }
34  MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 _T &__ref() noexcept {
35  return __v;
36  }
37 };
38 
39 // Empty case
40 // This doesn't work if _T is final, of course, but we're not using anything
41 // like that currently. That kind of thing could be added pretty easily though
42 template <class _T, size_t _Disambiguator>
44  _T, _Disambiguator,
45  enable_if_t<_MDSPAN_TRAIT(is_empty, _T) &&
46  // If the type isn't trivially destructible, its destructor
47  // won't be called at the right time, so don't use this
48  // specialization
49  _MDSPAN_TRAIT(is_trivially_destructible, _T)>> :
50 #ifdef _MDSPAN_COMPILER_MSVC
51  // MSVC doesn't allow you to access public static member functions of a type
52  // when you *happen* to privately inherit from that type.
53  protected
54 #else
55  // But we still want this to be private if possible so that we don't accidentally
56  // access members of _T directly rather than calling __ref() first, which wouldn't
57  // work if _T happens to be stateful and thus we're using the unspecialized definition
58  // of __no_unique_address_emulation above.
59  private
60 #endif
61  _T {
62  using __stored_type = _T;
63  MDSPAN_FORCE_INLINE_FUNCTION constexpr _T const &__ref() const noexcept {
64  return *static_cast<_T const *>(this);
65  }
66  MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 _T &__ref() noexcept {
67  return *static_cast<_T *>(this);
68  }
69 
70  MDSPAN_INLINE_FUNCTION_DEFAULTED
71  constexpr __no_unique_address_emulation() noexcept = default;
72  MDSPAN_INLINE_FUNCTION_DEFAULTED
74  __no_unique_address_emulation const &) noexcept = default;
75  MDSPAN_INLINE_FUNCTION_DEFAULTED
77  __no_unique_address_emulation &&) noexcept = default;
78  MDSPAN_INLINE_FUNCTION_DEFAULTED
79  _MDSPAN_CONSTEXPR_14_DEFAULTED __no_unique_address_emulation &
80  operator=(__no_unique_address_emulation const &) noexcept = default;
81  MDSPAN_INLINE_FUNCTION_DEFAULTED
82  _MDSPAN_CONSTEXPR_14_DEFAULTED __no_unique_address_emulation &
83  operator=(__no_unique_address_emulation &&) noexcept = default;
84  MDSPAN_INLINE_FUNCTION_DEFAULTED
85  ~__no_unique_address_emulation() noexcept = default;
86 
87  // Explicitly make this not a reference so that the copy or move
88  // constructor still gets called.
89  MDSPAN_INLINE_FUNCTION
90  explicit constexpr __no_unique_address_emulation(_T const& __v) noexcept : _T(__v) {}
91  MDSPAN_INLINE_FUNCTION
92  explicit constexpr __no_unique_address_emulation(_T&& __v) noexcept : _T(::std::move(__v)) {}
93 };
94 
95 //==============================================================================
96 
97 } // end namespace detail
98 } // end namespace experimental
99 } // end namespace std