Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <utility>
- #include <cassert>
- #include <functional>
- #include <algorithm>
- template<class...>
- class Tuple;
- template <>
- class Tuple<> {
- public:
- void swap(Tuple&) {}
- bool operator ==(const Tuple&) const {
- return true;
- }
- bool operator !=(const Tuple&) const {
- return false;
- }
- bool operator <=(const Tuple&) const {
- return true;
- }
- bool operator >=(const Tuple&) const {
- return true;
- }
- bool operator <(const Tuple&) const {
- return false;
- }
- bool operator >(const Tuple&) const {
- return false;
- }
- };
- template<class First, class... Others>
- class Tuple<First, Others...> {
- public:
- Tuple() : _first() {}
- Tuple(const Tuple&) = default;
- Tuple(Tuple&&) noexcept = default;
- template<class T, class... U>
- explicit Tuple(T&& first, U&&... others) noexcept : _first(std::forward<T>(first)), _other(std::forward<U>(others)...) {}
- Tuple& operator=(const Tuple&) = default;
- Tuple& operator=(Tuple&&) = default;
- template <class... U>
- friend class Tuple;
- void swap(Tuple& other) {
- std::swap(_first, other._first);
- _other.swap(other._other);
- }
- bool operator ==(const Tuple& t) const {
- return _first == t._first && _other == t._other;
- }
- bool operator < (const Tuple& t) const {
- return _first < t._first || (_first == t._first && _other < t._other);
- }
- bool operator > (const Tuple& t) const {
- return _first > t._first || (_first == t._first && _other > t._other);
- }
- bool operator !=(const Tuple& t) const {
- return !(*this == t);
- }
- bool operator <=(const Tuple& t) const {
- return !(*this > t);
- }
- bool operator >=(const Tuple& t) const {
- return !(*this < t);
- }
- template<size_t I, class Tpl, typename std::enable_if_t<(I > 0), int> = 0>
- decltype(auto) Get(Tpl&& t) {
- return Get<I - 1>(t._other);
- }
- template<size_t I, class Tpl, typename std::enable_if_t<(I == 0), int> = 0>
- decltype(auto) Get(Tpl&& t) {
- return (std::forward<Tpl>(t)._first);
- }
- template <typename T, typename Tpl, typename std::enable_if_t<std::is_same<decltype(std::decay_t<Tpl>::_first), T>::value, int> = 0>
- decltype(auto) Get(Tpl&& t) {
- return (std::forward<Tpl>(t)._first);
- }
- template <typename T, typename Tpl, typename std::enable_if_t<!std::is_same<decltype(std::decay_t<Tpl>::_first), T>::value, int> = 0>
- decltype(auto) Get(Tpl&& t) {
- return Get<T>(std::forward<Tpl>(t)._other);
- }
- template<class T, class U>
- decltype(auto) getTuple(T&& l, U&& r) {
- return mergeTuple(std::move(l), std::move(r));
- }
- template <class T>
- decltype(auto) getTuple(Tuple<> tup, T&& t) {
- return std::move(t);
- }
- template<class F, class... Others1, class... Others2>
- decltype(auto) getTup(Tuple<F, Others1...>&& tup1, Tuple<Others2...>&& tup2) {
- return Tuple<F, Others1..., Others2...>(std::move(tup1._first), tupleCat2(std::move(tup1._other), std::move(tup2)));
- }
- template <typename... Others1>
- decltype(auto) getTup(Tuple<>, Tuple<Others1...>&& tup) {
- return std::move(tup);
- }
- private:
- First _first;
- Tuple<Others...> _other;
- explicit Tuple(First&& first, Tuple<Others...>&& tup) noexcept : _first(std::move(first)), _other(std::move(tup)) {}
- };
- template <size_t I, class Tpl>
- decltype(auto) get(Tpl&& t){
- return t.template Get<I, Tpl>(std::forward<Tpl>(t));
- }
- template <class T, class Tpl>
- decltype(auto) get(Tpl&& t) {
- return t.template Get<T, Tpl>(std::forward<Tpl>(t));
- }
- template<class... Args>
- decltype(auto) makeTuple(Args&&... args) {
- return Tuple<std::decay_t<Args>...>(std::forward<Args>(args)...);
- }
- template<class Tup1, class Tup2>
- decltype(auto) tupleCat2(Tup1&& tup1, Tup2&& tup2) {
- return tup1.getTup(std::move(tup1), std::move(tup2));
- }
- template <class Tup>
- decltype(auto) tupleCat2(Tuple<>, Tup&& tup) {
- return std::move(tup);
- }
- template<class Tup1, class... Others>
- decltype(auto) tupleCat(Tup1&& tup, Others&&... others) {
- return tupleCat2(std::forward<Tup1>(tup), tupleCat(std::forward<Others>(others)...));
- }
- template <class Tup>
- decltype(auto) tupleCat(Tup&& tup) {
- return std::move(tup);
- }
- void test_tuple() {
- {
- Tuple<int, std::string, long> tuple;
- }
- {
- int test_int = 5;
- std::string test_string = "Hello";
- Tuple<int, std::string> tuple(test_int, test_string);
- }
- {
- int test_int = 5;
- std::string test_string = "Hello";
- std::vector<int> test_vector(10, 5);
- Tuple<int, std::string, std::vector<int>> tuple(test_int, test_string, std::move(test_vector));
- }
- {
- std::string test_string = "Hello";
- std::vector<int> test_vector(10, 5);
- Tuple<std::string, std::vector<int>> tuple(std::move(test_string), std::move(test_vector));
- }
- {
- Tuple<int> first(5);
- auto second = first;
- first.swap(second);
- auto third = std::move(first);
- assert(third == second);
- }
- {
- Tuple<int> first(12);
- auto second = first;
- assert(get<0>(first) == get<0>(second));
- second = Tuple<int>(14);
- assert(get<0>(second) == 14);
- first.swap(second);
- assert(get<0>(second) == 12);
- assert(get<0>(first) == 14);
- int&& test_int = get<0>(std::move(first));
- assert(test_int == 14);
- }
- {
- Tuple<int, long> tuple(12, 16);
- assert(get<int>(tuple) == 12);
- assert(get<long>(tuple) == 16);
- int test_int_lv = get<int>(tuple);
- int&& test_int_rv = get<int>(std::move(tuple));
- assert(test_int_lv == test_int_rv);
- }
- {
- Tuple<int, std::string, std::vector<int>> tuple = makeTuple(5, std::string("test"), std::vector<int>(2, 5));
- get<2>(tuple)[1] = 2;
- assert(get<2>(tuple)[1] == 2);
- }
- {
- int test_int = 1;
- auto tuple = makeTuple(test_int, std::ref(test_int));
- test_int = 2;
- assert(get<0>(tuple) == 1);
- assert(get<1>(tuple) == 2);
- }
- {
- std::vector<std::tuple<int, std::string, float>> v;
- v.emplace_back(2, "baz", -0.1);
- v.emplace_back(2, "bar", 3.14);
- v.emplace_back(1, "foo", 100.1);
- std::sort(v.begin(), v.end());
- assert(get<0>(v[0]) == 1);
- assert(get<0>(v[1]) == 2);
- assert(get<0>(v[2]) == 2);
- assert(get<1>(v[0]) == std::string("foo"));
- assert(get<1>(v[1]) == std::string("bar"));
- assert(get<1>(v[2]) == std::string("baz"));
- }
- {
- auto tuple = makeTuple(1, "hello");
- auto test_tuple = tupleCat(tuple, tuple, makeTuple(5, 10));
- assert(get<0>(test_tuple) == get<2>(test_tuple));
- assert(get<4>(test_tuple) == 5);
- }
- for (int i = 0; i < 10000; ++i) {
- Tuple<int, std::vector<int>> tuple(4, std::vector<int>(10000, 5));
- assert(get<int>(tuple) == 4);
- }
- }
- int main() {
- test_tuple();
- std::cout << 0;
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement