File: sbind1.cc

package info (click to toggle)
c%2B%2B-annotations 13.02.02-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 13,576 kB
  • sloc: cpp: 25,297; makefile: 1,523; ansic: 165; sh: 126; perl: 90; fortran: 27
file content (185 lines) | stat: -rw-r--r-- 3,226 bytes parent folder | download | duplicates (5)
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#include <iostream>
#include <tuple>

struct Cons1
{
    Cons1()
    {
        std::cout << "cons1\n";
    }

    Cons1(Cons1 const &other)
    {
        std::cout << "cons1 copycons\n";
    }

    void fun() const
    {
        std::cout << "cons1 fun\n";
    }
};


struct Cons2
{
    Cons2()
    {
        std::cout << "cons2\n";
    }

    Cons2(Cons2 const &other)
    {
        std::cout << "cons2 copycons\n";
    }

    void fun() const
    {
        std::cout << "cons2 fun\n";
    }
};

class Data
{
    Cons1 d_cons1;
    Cons2 d_cons2;

    public:
        Cons1 getCons() const
        {
            std::cout << "getCons():\n";
            return d_cons1;
        }
        Cons1 const &cons1() const
        {
            std::cout << "cons1():\n";
            return d_cons1;
        }
        Cons2 const &cons2() const
        {
            std::cout << "cons2():\n";
            return d_cons2;
        }

//    template <size_t Nr>
//    auto get() const
//    {
//        if constexpr (Nr == 0)
//            return getCons();
//
//        if constexpr (Nr == 1)
//            return cons1();
//
//        if constexpr (Nr == 2)
//            return cons2();
//
//        static_assert(Nr >= 0 and Nr < 3);
//    }
};

//instead of defining get as class member: it can also be defined
// outside of the class:
//
// template <size_t Nr>
// auto get(Data const &data)
// {
//     if constexpr (Nr == 0)
//         return data.getCons();
//
//     if constexpr (Nr == 1)
//         return data.cons1();
//
//     if constexpr (Nr == 2)
//         return data.cons2();
//
//     static_assert(Nr >= 0 and Nr < 3);
// }

// the return types can also be more precisely defined:
template <size_t Nr>
decltype(auto) get(Data const &data)
{
    if constexpr (Nr == 0)
        return data.getCons();

    if constexpr (Nr == 1)
//        return static_cast<Cons1 const &>(data.cons1());
        return data.cons1();

    if constexpr (Nr == 2)
//        return static_cast<Cons2 const &>(data.cons2());
        return data.cons2();

    static_assert(Nr >= 0 and Nr < 3);
}

    // in which case the tuple_element calls get(data):

template<size_t Nr>
struct std::tuple_element<Nr, Data>
{
    using type = decltype( get<Nr>( declval<Data>() ) );
};


    // same as below, explicitly inside namespace std:
template<>
struct std::tuple_size<Data>
{
    public:
    static size_t const value = 3;
};

namespace std
{

//template<>
//class tuple_size<Data>: public integral_constant<size_t, 3>
//{};
//
// Same:
//
//template<>
//struct tuple_size<Data>
//{
//    static size_t const value = 3;
//};


//template<size_t Nr>
//class tuple_element<Nr, Data>
//{
//    public:
//        using type = decltype(declval<Data>().get<Nr>());
//};


}

using namespace std;

int main()
{
    Data data;

    cout << "\n------\n\n";

        // copies data
//    auto [ a, b, c ] = data;        // here copy constructors are called,

        // uses data
    auto const &[ a, b, c ] = data;   // here copy constructors are called,
        // in all cases, a, b and c themselves are references.


    cout << "\n------\n\n";

    a.fun();

    cout << "\n------\n\n";

    b.fun();

    cout << "\n------\n\n";

    c.fun();
}