Эмулирую 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 . Предыдущая версия .
Re: Эмулирую tuples такие, какими они сделаны в python, матл
От: rg45 СССР  
Дата: 24.12.19 20:04
Оценка:
Здравствуйте, alexanderfedin, Вы писали:

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

A>Здесь можно попробовать: https://onlinegdb.com/H1AnA0k18
A>Не могу добиться того, чтобы код работал для результатов возврата функции.
A>Что-то у меня плохо с пониманием lvalue/rvalue.

Ага, плохо. Во фрагменте ниже функция to_tuple_works возвращает тупл ссылок: tuple <char&, int&, float&>.

    template <typename... T>
    tuple<T...> to_tuple_works(T&& ...a)
    {
        return tuple<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"
    );


Ты бы разобрался в базовых вещах для начала, потом бы уже эмулировал.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 24.12.2019 23:20 rg45 . Предыдущая версия . Еще …
Отредактировано 24.12.2019 20:06 rg45 . Предыдущая версия .
Re[2]: Эмулирую tuples такие, какими они сделаны в python, матл
От: alexanderfedin США http://alexander-fedin.pixels.com/
Дата: 25.12.19 00:52
Оценка:
Здравствуйте, rg45, Вы писали:
R>Ага, плохо. Во фрагменте ниже функция to_tuple_works возвращает тупл ссылок: tuple <char&, int&, float&>.
Насчет этого я в курсе, вопрос был "что я делаю не так".

R>Ты бы разобрался в базовых вещах для начала, потом бы уже эмулировал.

Конечно же я разберусь. Часть процесса "разобраться" — это как раз задание вопросов более опытным товарищам.
Правда, товарищи эти должны быть не только более опытными, но и желающими поделиться сокровенным знанием.

Вот, сделал: https://onlinegdb.com/Hy9aM4g1U
Respectfully,
Alexander Fedin.
Re[3]: Эмулирую tuples такие, какими они сделаны в python, матл
От: rg45 СССР  
Дата: 25.12.19 01:36
Оценка:
Здравствуйте, alexanderfedin, Вы писали:

R>>Ты бы разобрался в базовых вещах для начала, потом бы уже эмулировал.

A>Конечно же я разберусь. Часть процесса "разобраться" — это как раз задание вопросов более опытным товарищам.
A>Правда, товарищи эти должны быть не только более опытными, но и желающими поделиться сокровенным знанием.

A>Вот, сделал: https://onlinegdb.com/Hy9aM4g1U


Извини за прямоту, но этот код показывает то, что ты даже не пытался разбираться. Извращение на извращении сидит и извращением погоняет. Простейший класс превратил в дичь какую-то.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[3]: Эмулирую tuples такие, какими они сделаны в python, м
От: rg45 СССР  
Дата: 25.12.19 04:10
Оценка:
Здравствуйте, alexanderfedin, Вы писали:

A>Вот, сделал: https://onlinegdb.com/Hy9aM4g1U


Зачем делать сложным то, что проще простого. Все придумано до нас:

https://onlinegdb.com/Sk4YMvgJU

(Урезанная реализация)
    template <typename...> class tuple;
    template <> class tuple<> {};

    template <typename T, typename...U>
    class tuple<T, U...>
    {
    public:
        tuple() = default;

        template <typename X, typename...Y>
        tuple(X&& x, Y&&...y)
            : head_(std::forward<X>(x))
            , tail_(std::forward<Y>(y)...) { }

        template <typename X, typename...Y>
        tuple& operator = (const tuple<X, Y...>& t)
        {
            head_ = T(t.head_);
            tail_ = t.tail_;
            return *this;
        }

    private:
        template <typename...> friend class tuple;
        T head_;
        tuple<U...> tail_;
    };

    template <typename...T>
    tuple<T...> make_tuple(const T&...t) {
        return {t...};
    }

    template <typename...T>
    tuple<T&...> tie(T&...t) {
        return {t...};
    }
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 25.12.2019 4:18 rg45 . Предыдущая версия . Еще …
Отредактировано 25.12.2019 4:16 rg45 . Предыдущая версия .
Re: Эмулирую tuples такие, какими они сделаны в python, матлаб и
От: sergii.p  
Дата: 25.12.19 07:35
Оценка:
Здравствуйте, alexanderfedin, Вы писали:

A>Update: сделал: https://onlinegdb.com/Hy9aM4g1U


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


а почему нельзя сделать "exchange values python style" так?
    int i0 = 1;
    int i1 = 2;
    std::tie(i0, i1) = std::make_tuple(i1, i0);


и что такое tuple в Matlab, чем он отличается от реализации в С++? Трудно читать код (особенно шаблонный), когда не понимаешь какую задачу он решает
Re[2]: Эмулирую tuples такие, какими они сделаны в python, м
От: rg45 СССР  
Дата: 26.12.19 15:27
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>а почему нельзя сделать "exchange values python style" так?

SP>
SP>    int i0 = 1;
SP>    int i1 = 2;
SP>    std::tie(i0, i1) = std::make_tuple(i1, i0);
SP>


SP>и что такое tuple в Matlab, чем он отличается от реализации в С++? Трудно читать код (особенно шаблонный), когда не понимаешь какую задачу он решает


Как я понял, главная его фишка как раз в том, что нет разделения на tuple и tie. И выражение to_tuple(i0, i1) = to_tuple(i1, i0), действительно выполняет обмен, подобно swap. Чтобы этого добиться, ему пришлось запихнуть в свой tuple одновременно и ссылку, и значение. Конструкторы сделал закрытыми, оставив только возможность конструирования через фабричные функции. Расплатой за это стало то, что теперь нельзя сделать простейшую инициализацию: auto t = to_tuple(1, 2); Потому что внутри объекта тут же возникают протухшие ссылки. Это, кстати, не такое уж редкое явление среди разработчиков, когда человек сосредотачивается на какой-нибудь фишечке и приносит ей в жертву остальной функционал.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 26.12.2019 15:29 rg45 . Предыдущая версия .
Re[4]: Эмулирую tuples такие, какими они сделаны в python, м
От: alexanderfedin США http://alexander-fedin.pixels.com/
Дата: 26.12.19 19:14
Оценка:
Здравствуйте, rg45, Вы писали:
R>Зачем делать сложным то, что проще простого.
Последний раз до этого я писал на C++ в 2002-м году.
Шаблоны были, но совсем не такого уровня.

R>Все придумано до нас:

R>https://onlinegdb.com/Sk4YMvgJU
Спасибо!
Respectfully,
Alexander Fedin.
Отредактировано 26.12.2019 19:18 alexanderfedin . Предыдущая версия .
Re[4]: Эмулирую tuples такие, какими они сделаны в python, м
От: σ  
Дата: 27.12.19 06:40
Оценка:
А зачем head_, tail_? Чому не просто вложенный std::tuple?
Re[5]: Эмулирую tuples такие, какими они сделаны в python, м
От: rg45 СССР  
Дата: 27.12.19 06:55
Оценка:
Здравствуйте, σ, Вы писали:

σ>А зачем head_, tail_? Чому не просто вложенный std::tuple?


Ну мы же играем в игру, в которой std::tuple просто не существует. Иначе, зачем бы вообще городить огород.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[5]: Эмулирую tuples такие, какими они сделаны в python, м
От: rg45 СССР  
Дата: 27.12.19 07:01
Оценка:
Здравствуйте, alexanderfedin, Вы писали:

R>>https://onlinegdb.com/Sk4YMvgJU

A>Спасибо!

Я там head_ оставил без инициализации, в спешке. Нужно подправить:

T head_ {};
--
Не можешь достичь желаемого — пожелай достигнутого.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.