Created
July 9, 2024 03:47
-
-
Save DrkWithT/5bf1d13cbfa553d6736bc052a61accf4 to your computer and use it in GitHub Desktop.
My toy implementation of C++ STL pair class.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <type_traits> | |
#include <utility> | |
#include <stdexcept> | |
#include <print> | |
template <std::size_t Index, typename T1, typename T2> | |
struct TpChooser {}; | |
template <typename T1, typename T2> | |
struct TpChooser<0, T1, T2> | |
{ | |
using type = T1; | |
}; | |
template <typename T1, typename T2> | |
struct TpChooser<1, T1, T2> | |
{ | |
using type = T2; | |
}; | |
template <std::size_t Index, typename T1, typename T2> | |
using chosen_type_t = typename TpChooser<Index, T1, T2>::type; | |
template <std::size_t Pos, typename T> | |
class Cell | |
{ | |
private: | |
using naked_tp_t = std::remove_cv_t<T>; | |
naked_tp_t value; | |
public: | |
constexpr Cell() noexcept | |
: value {} {} | |
template <typename CT> | |
constexpr Cell(CT&& fw_arg) | |
: value {fw_arg} {} | |
void setValue(const T& next_value) | |
{ | |
this->value = next_value; | |
} | |
constexpr const naked_tp_t& getValue() const noexcept { return value; } | |
}; | |
template <typename T1, typename T2> | |
class Pair : public Cell<0, T1>, public Cell<1, T2> | |
{ | |
private: | |
using head_t = Cell<0, T1>; | |
using tail_t = Cell<1, T2>; | |
public: | |
static constexpr std::size_t length = 2; | |
constexpr Pair() noexcept | |
: head_t (), tail_t () {} | |
template <typename CT1, typename CT2> | |
constexpr Pair(CT1&& fw0, CT2&& fw1) | |
: head_t (fw0), tail_t (fw1) {} | |
constexpr const T1& getHead() const noexcept | |
{ | |
return head_t::getValue(); | |
} | |
constexpr const T2& getTail() const noexcept | |
{ | |
return tail_t::getValue(); | |
} | |
Pair<T1, T2>& operator=(const Pair<T1, T2>& other) noexcept | |
{ | |
if (&other == this) | |
return *this; | |
head_t::setValue(other.getHead()); | |
tail_t::setValue(other.getTail()); | |
return *this; | |
} | |
friend constexpr bool operator==(const Pair& lhs, const Pair& rhs) noexcept | |
{ | |
return lhs.getHead() == rhs.getHead() && lhs.getTail() == rhs.getTail(); | |
} | |
}; | |
template <typename T1, typename T2> | |
constexpr auto makePair(T1&& a, T2&& b) | |
{ | |
return Pair<T1, T2> {a, b}; | |
} | |
template <std::size_t Index, typename T1, typename T2> | |
constexpr auto getFromPairAt(const Pair<T1, T2>& arg) noexcept -> chosen_type_t<Index, T1, T2> | |
{ | |
static_assert(Index < arg.length); | |
if constexpr (Index == 0) | |
return arg.getHead(); | |
return arg.getTail(); | |
} | |
template <std::size_t Index, typename T1, typename T2> | |
constexpr auto getFromPairAt(const Pair<T1, T2>&& arg) noexcept -> chosen_type_t<Index, T1, T2> | |
{ | |
static_assert(Index < arg.length); | |
if constexpr (Index == 0) | |
return arg.getHead(); | |
return arg.getTail(); | |
} | |
int main() | |
{ | |
Pair<int, double> nums0; | |
auto nums1 = makePair(42, 10.5); | |
auto nums2 = makePair(69, 6.9); | |
std::print("nums0 = {}, {}\n", nums0.getHead(), nums0.getTail()); | |
std::print("nums1 = {}, {}\n", nums1.getHead(), nums1.getTail()); | |
std::print("nums2 = {}, {}\n", nums2.getHead(), nums2.getTail()); | |
std::print("nums0[0] = {}\n", getFromPairAt<0>(nums0)); | |
std::print("nums0[1] = {}\n", getFromPairAt<1>(nums0)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment