1 // Copyright 2019 The Fuchsia Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef LIB_STDCOMPAT_INTERNAL_CONSTRUCTORS_H_ 6 #define LIB_STDCOMPAT_INTERNAL_CONSTRUCTORS_H_ 7 8 #include <cstddef> 9 #include <type_traits> 10 #include <utility> 11 12 namespace cpp17 { 13 namespace internal { 14 15 // Mixin that implicitly deletes the subclass default constructor when type T 16 // is not default constructible. 17 template <typename T, bool = std::is_default_constructible<T>::value> 18 struct modulate_default_constructor {}; 19 template <typename T> 20 struct modulate_default_constructor<T, false> { 21 constexpr modulate_default_constructor() = delete; 22 }; 23 24 // Mixin that implicitly deletes the subclass copy constructor when type T is 25 // not copy constructible. 26 template <std::size_t Index, typename T, bool = std::is_copy_constructible<T>::value> 27 struct modulate_copy_constructor {}; 28 template <std::size_t Index, typename T> 29 struct modulate_copy_constructor<Index, T, false> { 30 constexpr modulate_copy_constructor() = default; 31 constexpr modulate_copy_constructor(const modulate_copy_constructor&) = delete; 32 constexpr modulate_copy_constructor& operator=(const modulate_copy_constructor&) = default; 33 constexpr modulate_copy_constructor(modulate_copy_constructor&&) = default; 34 constexpr modulate_copy_constructor& operator=(modulate_copy_constructor&&) = default; 35 }; 36 37 // Mixin that implicitly deletes the subclass copy assignment operator when type 38 // T is not copy assignable. 39 template <std::size_t Index, typename T, bool = std::is_copy_assignable<T>::value> 40 struct modulate_copy_assignment {}; 41 template <std::size_t Index, typename T> 42 struct modulate_copy_assignment<Index, T, false> { 43 constexpr modulate_copy_assignment() = default; 44 constexpr modulate_copy_assignment(const modulate_copy_assignment&) = default; 45 constexpr modulate_copy_assignment& operator=(const modulate_copy_assignment&) = delete; 46 constexpr modulate_copy_assignment(modulate_copy_assignment&&) = default; 47 constexpr modulate_copy_assignment& operator=(modulate_copy_assignment&&) = default; 48 }; 49 50 // Mixin that implicitly deletes the subclass move constructor when type T is 51 // not move constructible. 52 template <std::size_t Index, typename T, bool = std::is_move_constructible<T>::value> 53 struct modulate_move_constructor {}; 54 template <std::size_t Index, typename T> 55 struct modulate_move_constructor<Index, T, false> { 56 constexpr modulate_move_constructor() = default; 57 constexpr modulate_move_constructor(const modulate_move_constructor&) = default; 58 constexpr modulate_move_constructor& operator=(const modulate_move_constructor&) = default; 59 constexpr modulate_move_constructor(modulate_move_constructor&&) = delete; 60 constexpr modulate_move_constructor& operator=(modulate_move_constructor&&) = default; 61 }; 62 63 // Mixin that implicitly deletes the subclass move assignment operator when type 64 // T is not move assignable. 65 template <std::size_t Index, typename T, bool = std::is_move_assignable<T>::value> 66 struct modulate_move_assignment {}; 67 template <std::size_t Index, typename T> 68 struct modulate_move_assignment<Index, T, false> { 69 constexpr modulate_move_assignment() = default; 70 constexpr modulate_move_assignment(const modulate_move_assignment&) = default; 71 constexpr modulate_move_assignment& operator=(const modulate_move_assignment&) = default; 72 constexpr modulate_move_assignment(modulate_move_assignment&&) = default; 73 constexpr modulate_move_assignment& operator=(modulate_move_assignment&&) = delete; 74 }; 75 76 // Utility that takes an index sequence and an equally sized parameter pack and 77 // mixes in each of the above copy/move construction/assignment modulators for 78 // each type in Ts. The indices are used to avoid duplicate direct base errors 79 // by ensuring that each mixin type is unique, even when there are duplicate 80 // types within the parameter pack Ts. 81 template <typename IndexSequence, typename... Ts> 82 struct modulate_copy_and_move_index; 83 84 template <std::size_t... Is, typename... Ts> 85 struct modulate_copy_and_move_index<std::index_sequence<Is...>, Ts...> 86 : modulate_copy_constructor<Is, Ts>..., 87 modulate_copy_assignment<Is, Ts>..., 88 modulate_move_constructor<Is, Ts>..., 89 modulate_move_assignment<Is, Ts>... {}; 90 91 // Mixin that modulates the subclass copy/move constructors and assignment 92 // operators based on the copy/move characteristics of each type in Ts. 93 template <typename... Ts> 94 struct modulate_copy_and_move 95 : modulate_copy_and_move_index<std::index_sequence_for<Ts...>, Ts...> {}; 96 97 } // namespace internal 98 } // namespace cpp17 99 100 #endif // LIB_STDCOMPAT_INTERNAL_CONSTRUCTORS_H_ 101