For educational reasons I've decided to create my own CA. Here is what I learned.
Lets get some context first.
int main() | |
{ | |
B b(1, 'a', 'b', 'e'); | |
auto& [e1, e2, e3, e4] =b; | |
e1 = 100; | |
e2 = 'k'; | |
e3 = 'l'; | |
e4 = 'm'; | |
assert(100 == b.a); | |
assert('k' == b.c); |
template<std::size_t idx> decltype(auto) get(B &b) | |
{ | |
static_assert (idx < 4); | |
if constexpr (idx == 0) { | |
return static_cast<int&>(b.a); | |
} else if constexpr (idx == 1) { | |
return static_cast<char&>(b.c); | |
} else if constexpr (idx == 2) { | |
return static_cast<char&>(b.d); | |
} else { |
int main() | |
{ | |
B b(1, 'a', 'b', 'e'); | |
auto [e1, e2, e3, e4] = b; | |
assert(e1 == b.a); | |
assert(e2 == b.c); | |
assert(e3 == b.d); | |
assert(e4 == b.e); | |
} |
template<std::size_t idx> auto get(const B &b) | |
{ | |
static_assert (idx < 4); | |
if constexpr (idx == 0) { | |
return b.a; | |
} else if constexpr (idx == 1) { | |
return b.c; | |
} else if constexpr (idx == 2) { | |
return b.d; | |
} else { |
template<std::size_t> auto get(const B&); | |
template<> auto get<0>(const B &b) { return b.a; } | |
template<> auto get<1>(const B &b) { return b.c; } | |
template<> auto get<2>(const B &b) { return b.d; } | |
template<> auto get<3>(const B &b) { return b.e; } |
template<> | |
struct std::tuple_element<0, B> | |
{ | |
using type = int; | |
}; | |
template<std::size_t idx> | |
struct std::tuple_element<idx, B> | |
{ | |
using type = char; |
template<> | |
struct std::tuple_size<B> | |
{ | |
static constexpr int value = 4; | |
}; |
struct A { | |
explicit A(int a) : a(a) {} | |
int a; | |
}; | |
struct B : public A { | |
B(int a, char c, char d, char e) : A(a), c(c), d(d), e(e) {} | |
char c; | |
char d; | |
char e; |
struct RetVal | |
{ | |
int x; | |
int& y; | |
const int& z; | |
}; | |
RetVal doSomething(int& a, const int &b) { | |
return {10, a, b}; | |
} |