#pragma once #include "RE/M/MemoryManager.h" namespace RE { template class BSTTuple { public: using first_type = T1; using second_type = T2; // 1) BSTTuple() // noexcept(std::is_nothrow_default_constructible_v && std::is_nothrow_default_constructible_v) // requires(std::is_default_constructible_v && std::is_default_constructible_v) : first(), second() {} // 2) explicit(!std::is_convertible_v || !std::is_convertible_v) // BSTTuple(const first_type& a_first, const second_type& a_second) // noexcept(std::is_nothrow_copy_constructible_v && std::is_nothrow_copy_constructible_v) // requires(std::is_copy_constructible_v && std::is_copy_constructible_v) : first(a_first), second(a_second) {} // 3) template explicit(!std::is_convertible_v || !std::is_convertible_v) // BSTTuple(U1&& a_first, U2&& a_second) // noexcept(std::is_nothrow_constructible_v && std::is_nothrow_constructible_v) // requires(std::is_constructible_v && std::is_constructible_v) : first(std::forward(a_first)), second(std::forward(a_second)) {} // 4) template explicit(!std::is_convertible_v || !std::is_convertible_v) // BSTTuple(const BSTTuple& a_rhs) // noexcept(std::is_nothrow_constructible_v && std::is_nothrow_constructible_v) // requires(std::is_constructible_v && std::is_constructible_v) : first(a_rhs.first), second(a_rhs.second) {} // 5) template explicit(!std::is_convertible_v || !std::is_convertible_v) // BSTTuple(BSTTuple&& a_rhs) // noexcept(std::is_nothrow_constructible_v && std::is_nothrow_constructible_v) // requires(std::is_constructible_v && std::is_constructible_v) : first(std::forward(a_rhs.first)), second(std::forward(a_rhs.second)) {} // 6) template < class... Args1, class... Args2> BSTTuple(std::piecewise_construct_t, std::tuple a_firstArgs, std::tuple a_secondArgs) : BSTTuple(a_firstArgs, a_secondArgs, std::index_sequence_for(), std::index_sequence_for()) {} private: // 6) impl template < class Tuple1, class Tuple2, std::size_t... I1, std::size_t... I2> BSTTuple(Tuple1& a_firstArgs, Tuple2& a_secondArgs, std::index_sequence, std::index_sequence) : first(std::get(std::move(a_firstArgs))...), second(std::get(std::move(a_secondArgs))...) {} public: // 7) BSTTuple(const BSTTuple&) = default; // 8) BSTTuple(BSTTuple&&) = default; ~BSTTuple() = default; // 1) BSTTuple& operator=(const BSTTuple& a_rhs) // noexcept(std::is_nothrow_copy_assignable_v && std::is_nothrow_copy_assignable_v) // requires(std::is_copy_assignable_v && std::is_copy_assignable_v) { if (this != std::addressof(a_rhs)) { first = a_rhs.first; second = a_rhs.second; } return *this; } // 2) template BSTTuple& operator=(const BSTTuple& a_rhs) // noexcept(std::is_nothrow_assignable_v && std::is_nothrow_assignable_v) // requires(std::is_assignable_v && std::is_assignable_v) { first = a_rhs.first; second = a_rhs.second; return *this; } // 3) BSTTuple& operator=(BSTTuple&& a_rhs) // noexcept(std::is_nothrow_move_assignable_v && std::is_nothrow_move_assignable_v) // requires(std::is_move_assignable_v && std::is_move_assignable_v) { if (this != std::addressof(a_rhs)) { first = std::move(a_rhs.first); second = std::move(a_rhs.second); } return *this; } // 4) template BSTTuple& operator=(BSTTuple&& a_rhs) // noexcept(std::is_nothrow_assignable_v && std::is_nothrow_assignable_v) // requires(std::is_assignable_v && std::is_assignable_v) { first = std::move(a_rhs.first); second = std::move(a_rhs.second); return *this; } F4_HEAP_REDEFINE_NEW(BSTTuple); void swap(BSTTuple& a_rhs) // noexcept(std::is_nothrow_swappable_v && std::is_nothrow_swappable_v) { using std::swap; if (this != std::addressof(a_rhs)) { swap(first, a_rhs.first); swap(second, a_rhs.second); } } // members first_type first; // 00 second_type second; // ?? }; template [[nodiscard]] auto make_pair(T1&& a_first, T2&& a_second) { using result_t = BSTTuple< std::decay_t, std::decay_t>; return result_t(std::forward(a_first), std::forward(a_second)); } template [[nodiscard]] auto make_tuple(T1&& a_first, T2&& a_second) { using result_t = BSTTuple< std::decay_t, std::decay_t>; return result_t(std::forward(a_first), std::forward(a_second)); } template [[nodiscard]] bool operator==(const BSTTuple& a_lhs, const BSTTuple& a_rhs) { return a_lhs.first == a_rhs.first && a_lhs.second == a_rhs.second; } template [[nodiscard]] bool operator<(const BSTTuple& a_lhs, const BSTTuple& a_rhs) { return a_lhs.first < a_rhs.first ? true : a_rhs.first < a_lhs.first ? false : a_lhs.second < a_rhs.second ? true : false; } template void swap(BSTTuple& a_lhs, BSTTuple& a_rhs) // noexcept(noexcept(a_lhs.swap(a_rhs))) // requires(std::is_swappable_v && std::is_swappable_v) { a_lhs.swap(a_rhs); } template BSTTuple(T1, T2) -> BSTTuple; }