summaryrefslogtreecommitdiffstats
path: root/include/containers/Tuple.h
blob: cf870d1237d1d482e537d3838b2986ee58b07598 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#ifndef CONTAINERSTUPLE_H
#define CONTAINERSTUPLE_H


#include <Templates.h>

template<typename Head = void, typename ... Tail>
class Tuple : public Tuple<Tail ...>
{
    private:
        using valueType = Head;
        valueType value;
    public:
        using baseType = Tuple<Tail ...>;
        Tuple(Head val_, Tail ... args) : baseType(args ...), value(val_) {};

        static constexpr unsigned int length() {return sizeof...(Tail) + 1;}
        valueType getValue() {return value;};

        template<uint16 indx>
        auto get()
        {
            using returnType = cut<indx, Tuple>::process::result;
            return static_cast<returnType>(*this);
        };

        /* 
        Create the class/struct before using the method
        F is this class/struct to pass in method trought template argument.
        F must contain a static method/s named "perform"
        that will perform something action for every value in tuple object.
        F must contain as many implementations
        as there are different types in the template
        F::perform() for the first argument accept tuple value,
        next arguments optional
        */
        template<typename F, uint16 If = length() - 1, uint16 ... I,
                 typename Mid = void, typename ... T>
        void foreach(T ... arg)
        {
            if constexpr(If != NULL)
            {
                foreach<F, If - 1, If, I ...>(arg ...);
            }
            else
            {
                (F::perform(get<If>().getValue(), arg ...));
                (F::perform(get<I>().getValue(), arg ...), ...);
            }
        };
};

template<>
class Tuple<>
{
    public:
        static constexpr unsigned int length() {return 0;}
};

template<typename Head>
class Tuple<Head>
{
    private:
        using valueType = Head;
        valueType value;
    public:
        using baseType = Tuple<>;
        Tuple(Head val_) : value(val_) {};
        Tuple() : value(valueType()) {};

        static constexpr unsigned int length() {return 1;}
        valueType getValue() {return value;};

        template<uint16 indx>
        auto get()
        {
            if constexpr (indx == NULL) return *this;
            else static_assert(!indx, "Tuple::get<indx>: Out of bounds");
        };

        /*
        Create the class/struct before using the method
        F is this class/struct to pass in method trought template argument.
        F must contain a static method/s named "perform"
        that will perform something action for every value in tuple object.
        F must contain as many implementations
        as there are different types in the template
        F::perform() for the first argument accept tuple value,
        next arguments optional
        */
        template<typename F, typename ... T>
        void foreach(T ... arg)
        {
            F::perform(value, arg ...);
        };
};

#endif