/******************************************************************************
Welcome to GDB Online.
GDB online is an online compiler and debugger tool for C, C++, Python, PHP, Ruby,
C#, VB, Perl, Swift, Prolog, Javascript, Pascal, HTML, CSS, JS
Code, Compile, Run and Debug online from anywhere in world.
*******************************************************************************/
#include <iostream>
#include <type_traits>
#include <utility>
namespace std
{
template <typename T>
using remove_reference_t = typename remove_reference<T>::type;
template <typename T>
using remove_cv_t = typename remove_cv<T>::type;
template <typename T>
using remove_cvr = remove_reference<typename remove_cv<T>::type>;
template <typename T>
using remove_cvr_t = typename remove_cvr<T>::type;
}
namespace matlab
{
namespace details
{
using namespace ::std;
template <size_t I, typename T0, typename... T>
class tuple_impl
{
using this_type = tuple_impl<I, T0, T...>;
using next_type = tuple_impl<I - 1, T...>;
using value_type = std::remove_cvr_t<T0>;
value_type c;
value_type& v;
next_type _i;
public:
tuple_impl(T0 &a0, T&... a) :
_i(a...),
c(a0), v(a0)
{
}
this_type &operator=(const this_type &that)
{
_i = that._i;
v = that.c;
return *this;
}
};
template <typename T0>
class tuple_impl<0, T0>
{
using this_type = tuple_impl<0, T0>;
using value_type = remove_cvr_t<T0>;
value_type c;
value_type& v;
public:
tuple_impl(value_type &a0) :
c(a0), v(a0)
{
}
this_type &operator=(const this_type &that)
{
v = that.c;
return *this;
}
};
template <typename T>
static std::remove_cvr_t<T> const_to_value(const T& v)
{
return v;
}
}
template <typename... T>
class m_tuple
{
using this_type = m_tuple<T...>;
using impl_type = details::tuple_impl<sizeof...(T) - 1, std::remove_cvr_t<T>...>;
impl_type _i;
m_tuple(T&... a) :
_i(a...)
{}
public:
static inline this_type make(T&... a)
{
return m_tuple<T...>(a...);
}
m_tuple(const this_type &that) :
_i(that._i)
{}
m_tuple& operator=(const m_tuple& that)
{
_i = that._i;
return *this;
}
};
template <typename... T>
m_tuple<T...> to_tuple(T& ...a)
{
return m_tuple<T...>::make(a...);
}
template <typename... T>
m_tuple<T...> to_tuple(T&& ...a)
{
return to_tuple(static_cast<T&>(a)...);
}
template <typename... T>
m_tuple<T...> to_tuple(const T& ...a)
{
return to_tuple(details::const_to_value<T>(a)...);
}
namespace instant_tests
{
char ch = 0;
int ii = 123;
float ff = 2.7;
static_assert(
std::is_same<
m_tuple<char, int, float>,
decltype(to_tuple(ch, ii, ff))>::value,
"fails"
);
}
}
using namespace matlab;
m_tuple<int, float> foo(int a, float b)
{
int aa = a * a;
float bb = b * b;
return to_tuple(aa, bb);
}
float bar(int a, float b)
{
int aa = {};
float bb = {};
to_tuple(aa, bb) = foo(a, b);//decompose results
return aa + bb;
}
int main()
{
using namespace std;
using namespace matlab;
int i0 = 123, i1 = 42;
float f0 = 2.7, f1 = 3.14;
cout << "Before" << endl;
cout << "i0: " << i0 << endl;
cout << "f0: " << f0 << endl;
cout << "i1: " << i1 << endl;
cout << "f1: " << f1 << endl << endl;
to_tuple(i0, f0) = to_tuple(i1, f1);
cout << "After" << endl;
cout << "i0: " << i0 << endl;
cout << "f0: " << f0 << endl;
cout << "i1: " << i1 << endl;
cout << "f1: " << f1 << endl << endl << endl;
i0 = 123;
cout << "Before exchange" << endl;
cout << "i0: " << i0 << endl;
cout << "i1: " << i1 << endl << endl;
to_tuple(i0, i1) = to_tuple(i1, i0);//exchange values python style
cout << "After exchange" << endl;
cout << "i0: " << i0 << endl;
cout << "i1: " << i1 << endl << endl;
auto r = bar(2, 3);
cout << "After bar" << endl;
cout << "r: " << r << endl << endl;
to_tuple(i0, i1) = to_tuple(1, 2);
cout << "After assign to literals" << endl;
cout << "i0: " << i0 << endl;
cout << "i1: " << i1 << endl << endl;
const int x = 2;
const int y = 3;
to_tuple(i0, i1) = to_tuple(x, y);
cout << "After assign to constants" << endl;
cout << "i0: " << i0 << endl;
cout << "i1: " << i1 << endl;
return 0;
}