Эмулирую tuples такие, какими они сделаны в python, матлаб и
От: alexanderfedin США http://alexander-fedin.pixels.com/
Дата: 24.12.19 18:58
Оценка:
Update: сделал: https://onlinegdb.com/Hy9aM4g1U

С++11, ибо цель — библиотека поддержки транслятора с матлаба в CUDA C++.

Здесь можно попробовать: https://onlinegdb.com/H1AnA0k18
Не могу добиться того, чтобы код работал для результатов возврата функции.
Что-то у меня плохо с пониманием lvalue/rvalue.
#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 base_type = tuple_impl<I - 1, T...>;
            using value_type = std::remove_cvr_t<T0>;
        
            const value_type c;
            value_type& v;
            base_type _i;
        
        public:
            tuple_impl() :
                c({}), v(c)
            {
            }
            
            tuple_impl(this_type &&that) :
                _i(forward<base_type>(that._i)),
                c(that.c), v(that.v)
            {
            }
            
            tuple_impl(const this_type &that) :
                _i(that._i),
                c(that.c), v(that.v)
            {
            }
            
            tuple_impl(T0 &arg0, T&&... args) :
                _i(forward<T>(args)...),
                c(arg0), v(arg0)
            {
            }
            
            this_type &operator=(const this_type &that)
            {
                //for onlineGDB only, as it automatically shows only local vars
                const auto &this_i = _i;
                const auto &that_i = that._i;
        
                _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>;
        
            const value_type c;
            value_type& v;
            
        public:
            tuple_impl() :
                c({}), v(c)
            {
            }
            
            tuple_impl(this_type &&that) :
                c(that.c), v(that.v)
            {
            }
            
            tuple_impl(const this_type &that) :
                c(that.c), v(that.v)
            {
            }
            
            tuple_impl(value_type &arg0) :
                c(arg0), v(arg0)
            {
            }
            
            this_type &operator=(const this_type &that)
            {
                //for onlineGDB only, as it automatically shows only local vars
                const auto &this_i = *this;
                const auto &that_i = that;
        
                v = that.c;
        
                return *this;
            }
        };
    }
    
    template <typename... T>
    class tuple
    {
        using this_type = tuple<T...>;
        using impl = details::tuple_impl<sizeof...(T) - 1, T...>;
        
        impl _i;
        
    public:
        tuple(this_type &&that) :
            _i(std::forward<impl>(that._i))
        {}
        
        tuple(const this_type &that) :
            _i(that._i)
        {}
        
        tuple(T&&... args) :
            _i(std::forward<T>(args)...)
        {}
        
        // operator const this_type &() const
        // {
        //     return const_cast<const this_type &>(*this);
        // }
        
        tuple& operator=(const tuple& that)
        {
            //for onlineGDB only, as it automatically shows only local vars
            auto &this_i = *this;
            auto &that_i = that;
            
            _i = that._i;
    
            return *this;
        }
    };
    
    using namespace std;

    template <typename... T>
    tuple<T...> to_tuple_works(T&& ...a)
    {
        return tuple<T...>(std::forward<T>(a)...);
    }

    template <typename... T>
    tuple<std::remove_cvr_t<T>...> to_tuple_fails(T&& ...a)
    {
        return tuple<std::remove_cvr_t<T>...>(std::forward<T>(a)...);
    }
    
    char ch = 0;
    int ii = 123;
    float ff = 2.7;
    static_assert(
        std::is_same<
            tuple<char, int, float>,
            decltype(to_tuple_works(ch, ii, ff))>::value,
        "fails"
    );
}

matlab::tuple<int, float> foo_fails(int a, float b)
{
    int aa = a * a;
    float bb = b * b;
    return matlab::to_tuple_fails(aa, bb);
}

float bar(int a, float b)
{
    int aa = {};
    float bb = {};
    matlab::to_tuple_fails(aa, bb) = foo_fails(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_works(i0, f0) = to_tuple_works(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_works(i0, i1) = to_tuple_works(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;
    
    return 0;
}
Respectfully,
Alexander Fedin.
Отредактировано 25.12.2019 0:55 alexanderfedin . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.