Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma once
- #include <utility>
- using std::forward;
- using std::move;
- using std::enable_if;
- template <size_t N, typename FIRST, typename... OTHERS>
- struct KthType {
- typedef typename KthType<N-1, OTHERS...>::type type;
- };
- template <typename FIRST, typename... OTHERS>
- struct KthType<0, FIRST, OTHERS...> {
- typedef FIRST type;
- };
- template <typename FIRST, typename... OTHERS>
- class Tuple {
- public:
- Tuple() = default;
- Tuple(const Tuple<FIRST, OTHERS...>&) = default;
- Tuple(Tuple<FIRST, OTHERS...>&&);
- template <typename FARG, typename... ARGS>
- explicit Tuple(FARG&&, ARGS&&...);
- Tuple<FIRST, OTHERS...>& operator=(const Tuple<FIRST, OTHERS...>&);
- Tuple<FIRST, OTHERS...>& operator=(Tuple<FIRST, OTHERS...>&&);
- ~Tuple() = default;
- void swap(Tuple<FIRST, OTHERS...>&);
- //friends
- template <size_t N, typename FST, typename... OTH>
- friend class GetByNum;
- template <typename T, typename FST, typename... OTH>
- friend class GetByType;
- template <typename FST, typename... OTH>
- friend class Compares;
- template <typename TUPLE1, typename TUPLE2>
- friend class Cat2;
- private:
- FIRST _fst;
- Tuple<OTHERS...> _others;
- Tuple(FIRST&&, Tuple<OTHERS...>&&);
- };
- template <typename T>
- class Tuple<T> {
- public:
- Tuple() = default;
- Tuple(const Tuple<T>&) = default;
- Tuple(Tuple<T>&&);
- template <typename U>
- explicit Tuple(U&&);
- Tuple<T>& operator=(const Tuple<T>&);
- Tuple<T>& operator=(Tuple<T>&&);
- ~Tuple() = default;
- void swap(Tuple<T>&);
- //friends
- template <size_t N, typename FST, typename... OTH>
- friend class GetByNum;
- template <typename U, typename FST, typename... OTH>
- friend class GetByType;
- template <typename FST, typename... OTH>
- friend class Compares;
- template <typename TUPLE1, typename TUPLE2>
- friend class Cat2;
- private:
- T _fst;
- };
- // Implementation
- // Construct
- template <typename FIRST, typename... OTHERS>
- template <typename FARG, typename... ARGS>
- Tuple<FIRST, OTHERS...>::Tuple(FARG&& farg, ARGS&&... args):
- _fst(forward<FARG>(farg)),
- _others(forward<ARGS>(args)...) {}
- template <typename T>
- template <typename U>
- Tuple<T>::Tuple(U&& value):_fst(forward<U>(value)) {}
- template <typename FIRST, typename... OTHERS>
- Tuple<FIRST, OTHERS...>::Tuple(Tuple<FIRST, OTHERS...>&& tuple):
- _fst(forward<FIRST>(tuple._fst)),
- _others(move(tuple._others)) {}
- template <typename T>
- Tuple<T>::Tuple(Tuple<T>&& tuple):
- _fst(forward<T>(tuple._fst)) {}
- template <typename FIRST, typename... OTHERS>
- Tuple<FIRST, OTHERS...>::Tuple(FIRST&& fst,
- Tuple<OTHERS...>&& oth):
- _fst(move(fst)),
- _others(move(oth))
- {}
- // Copy
- template <typename FIRST, typename... ARGS>
- Tuple<FIRST, ARGS...>& Tuple<FIRST, ARGS...>::operator=
- (Tuple<FIRST, ARGS...>&& tuple) {
- _fst = move(tuple._fst);
- _others = move(tuple._others);
- return *this;
- }
- template <typename T>
- Tuple<T>& Tuple<T>::operator=(Tuple<T>&& tuple) {
- _fst = move(tuple._fst);
- return *this;
- }
- template <typename FIRST, typename... ARGS>
- Tuple<FIRST, ARGS...>& Tuple<FIRST, ARGS...>::operator=
- (const Tuple<FIRST, ARGS...>& tuple) {
- _fst = tuple._fst;
- _others = tuple._others;
- return *this;
- }
- template <typename T>
- Tuple<T>& Tuple<T>::operator=(const Tuple<T>& tuple) {
- _fst = tuple._fst;
- return *this;
- }
- template <class T>
- struct unwrap_refwrapper {
- using type = T;
- };
- template <class T>
- struct unwrap_refwrapper<std::reference_wrapper<T> > {
- using type = T&;
- };
- template <class T>
- using special_decay_t = typename unwrap_refwrapper<typename std::decay<T>::type>::type;
- template <typename... ARGS>
- auto makeTuple(ARGS&&... args) {
- return Tuple<special_decay_t<ARGS>...>
- (forward<ARGS>(args)...);
- }
- // Swap
- template <typename FST, typename... OTHERS>
- void Tuple<FST, OTHERS...>::swap(Tuple<FST, OTHERS...>& tuple) {
- std::swap(_fst, tuple._fst);
- std::swap(_others, tuple._others);
- }
- template <typename T>
- void Tuple<T>::swap(Tuple<T>& tuple) {
- std::swap(_fst, tuple._fst);
- }
- // Get By Num
- template <size_t N, typename FIRST, typename... OTHERS>
- struct GetByNum {
- static decltype(auto)
- action(Tuple<FIRST, OTHERS...>& tuple) {
- return GetByNum<N-1, OTHERS...>::action(tuple._others);
- }
- static decltype(auto)
- action(const Tuple<FIRST, OTHERS...>& tuple) {
- return GetByNum<N-1, OTHERS...>::action(tuple._others);
- }
- static decltype(auto)
- action(Tuple<FIRST, OTHERS...>&& tuple) {
- return GetByNum<N-1, OTHERS...>::action(move(tuple._others));
- }
- };
- template <typename FIRST, typename... OTHERS>
- struct GetByNum<0, FIRST, OTHERS...> {
- static FIRST& action(Tuple<FIRST, OTHERS...>& tuple) {
- return tuple._fst;
- }
- static const FIRST& action(const Tuple<FIRST, OTHERS...>& tuple) {
- return tuple._fst;
- }
- static FIRST&& action(Tuple<FIRST, OTHERS...>&& tuple) {
- return move(tuple._fst);
- }
- };
- template <size_t N, typename FIRST, typename... OTHERS>
- decltype(auto) get(Tuple<FIRST, OTHERS...>& tuple) {
- return GetByNum<N, FIRST, OTHERS...>::action(tuple);
- };
- template <size_t N, typename FIRST, typename... OTHERS>
- decltype(auto) get(const Tuple<FIRST, OTHERS...>& tuple) {
- return GetByNum<N, FIRST, OTHERS...>::action(tuple);
- };
- template <size_t N, typename FIRST, typename... OTHERS>
- decltype(auto) get(Tuple<FIRST, OTHERS...>&& tuple) {
- return GetByNum<N, FIRST, OTHERS...>::action(move(tuple));
- };
- // Get By Type
- template <typename T, typename FIRST, typename... OTHERS>
- struct GetByType {
- static T& action (Tuple<FIRST, OTHERS...>& tuple) {
- return GetByType<T, OTHERS...>::action(tuple._others);
- }
- static const T& action (const Tuple<FIRST, OTHERS...>& tuple) {
- return GetByType<T, OTHERS...>::action(tuple._others);
- }
- static T&& action (Tuple<FIRST, OTHERS...>&& tuple) {
- return GetByType<T, OTHERS...>::action(move(tuple._others));
- }
- };
- template <typename T, typename... OTHERS>
- struct GetByType<T, T, OTHERS...> {
- static T& action (Tuple<T, OTHERS...>& tuple) {
- return tuple._fst;
- }
- static T&& action (Tuple<T, OTHERS...>&& tuple) {
- return move(tuple._fst);
- }
- static const T& action (const Tuple<T, OTHERS...>& tuple) {
- return tuple._fst;
- }
- };
- template <typename T, typename FIRST, typename... OTHERS>
- T& get(Tuple<FIRST, OTHERS...>& tuple) {
- return GetByType<T, FIRST, OTHERS...>::action(tuple);
- };
- template <typename T, typename FIRST, typename... OTHERS>
- const T& get(const Tuple<FIRST, OTHERS...>& tuple) {
- return GetByType<T, FIRST, OTHERS...>::action(tuple);
- };
- template <typename T, typename FIRST, typename... OTHERS>
- T&& get(Tuple<FIRST, OTHERS...>&& tuple) {
- return GetByType<T, FIRST, OTHERS...>::action(move(tuple));
- };
- // Compare
- template <typename FIRST, typename... OTHERS>
- struct Compares {
- static bool equial(const Tuple<FIRST, OTHERS...>& fst,
- const Tuple<FIRST, OTHERS...>& scnd) {
- if (fst._fst == scnd._fst) {
- return Compares<OTHERS...>::equial(fst._others, scnd._others);
- } else {
- return false;
- }
- };
- static bool less(const Tuple<FIRST, OTHERS...>& fst,
- const Tuple<FIRST, OTHERS...>& scnd) {
- if (fst._fst == scnd._fst) {
- return Compares<OTHERS...>::less(fst._others, scnd._others);
- } else {
- return fst._fst < scnd._fst;
- }
- };
- };
- template <typename T>
- struct Compares<T> {
- static bool equial(const Tuple<T>& fst,
- const Tuple<T>& scnd) {
- return fst._fst == scnd._fst;
- }
- static bool less(const Tuple<T>& fst,
- const Tuple<T>& scnd) {
- return fst._fst < scnd._fst;
- }
- };
- template <typename FIRST, typename... OTHERS>
- bool operator==(const Tuple<FIRST, OTHERS...>& fst,
- const Tuple<FIRST, OTHERS...>& scnd) {
- return Compares<FIRST, OTHERS...>::equial(fst, scnd);
- };
- template <typename FIRST, typename... OTHERS>
- bool operator!=(const Tuple<FIRST, OTHERS...>& fst,
- const Tuple<FIRST, OTHERS...>& scnd) {
- return not (fst == scnd);
- };
- template <typename FIRST, typename... OTHERS>
- bool operator<(const Tuple<FIRST, OTHERS...>& fst,
- const Tuple<FIRST, OTHERS...>& scnd) {
- return Compares<FIRST, OTHERS...>::less(fst, scnd);
- };
- template <typename FIRST, typename... OTHERS>
- bool operator>(const Tuple<FIRST, OTHERS...>& fst,
- const Tuple<FIRST, OTHERS...>& scnd) {
- return scnd < fst;
- };
- template <typename FIRST, typename... OTHERS>
- bool operator>=(const Tuple<FIRST, OTHERS...>& fst,
- const Tuple<FIRST, OTHERS...>& scnd) {
- return not (fst < scnd);
- };
- template <typename FIRST, typename... OTHERS>
- bool operator<=(const Tuple<FIRST, OTHERS...>& fst,
- const Tuple<FIRST, OTHERS...>& scnd) {
- return not (scnd < fst);
- };
- template <typename TUPLE1, typename TUPLE2>
- class Cat2;
- template <typename FST1, typename... OTH1, typename FST2, typename... OTH2>
- struct Cat2<Tuple<FST1, OTH1...>, Tuple<FST2, OTH2...> > {
- static Tuple<FST1, OTH1..., FST2, OTH2...>
- action(Tuple<FST1, OTH1...> ftup,
- Tuple<FST2, OTH2...> stup) {
- return Tuple<FST1, OTH1..., FST2, OTH2...>
- (move(ftup._fst), Cat2<Tuple<OTH1...>,
- Tuple<FST2, OTH2...> >::action(move(ftup._others), move(stup)));
- }
- };
- template <typename T, typename FST, typename... OTH>
- struct Cat2<Tuple<T>, Tuple<FST, OTH...> > {
- static Tuple<T, FST, OTH...>
- action(Tuple<T> ftup,
- Tuple<FST, OTH...> stup) {
- return Tuple<T, FST, OTH...>(move(ftup._fst), move(stup));
- }
- };
- template <typename... TUPS>
- struct ResOfCat;
- template <typename TUP>
- struct ResOfCat<TUP> {
- typedef TUP type;
- };
- template <typename FST1, typename... OTH1, typename FST2, typename... OTH2>
- struct ResOfCat <Tuple<FST1, OTH1...>, Tuple<FST2, OTH2...> > {
- typedef Tuple<FST1, OTH1..., FST2, OTH2...> type;
- };
- template <typename TUP1, typename... TUPOTH>
- struct ResOfCat <TUP1, TUPOTH...> {
- typedef typename ResOfCat<TUP1, typename ResOfCat<TUPOTH...>::type>::type type;
- };
- template <typename TUPFST, typename... TUPOTH>
- struct Cat {
- typedef Cat<TUPOTH...> son;
- typedef typename ResOfCat<TUPFST, TUPOTH...>::type result;
- static result
- action(TUPFST fst, TUPOTH... oth) {
- return Cat2<TUPFST, typename son::result>::action(move(fst),
- son::action(move(oth)...));
- }
- };
- template <typename TUP>
- struct Cat<TUP> {
- typedef TUP result;
- static TUP action(TUP tuple) { return tuple; }
- };
- template <typename... TUPS>
- decltype(auto) tupleCat(TUPS&&... tups) {
- return Cat<std::remove_const_t<std::remove_reference_t<TUPS> >...>::
- action(forward<TUPS>(tups)...);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement