Re[2]: подскажите как пофиксить код
От: Evgeny.Panasyuk Россия  
Дата: 22.09.14 11:09
Оценка: 15 (1)
Здравствуйте, Кодт, Вы писали:

К>А в случае с кортежом произвольной размерности — фиг.

К>Компилятор позволяет или сразу подставить список аргументов-скаляров в конструктор (тогда можно создать некопируемый-неперемещаемый кортеж), или должен прибегнуть к рекурсии.
К>А для рекурсии нужно копирование-перемещение, либо особая макросная магия — как в старом добром C++98.

О чём речь?
Создать tuple с non-movable & non-copyable полями и конструировать их piecewise из набора кортежей аргументов — принципиально возможно.
Вот черновик:
#include <iostream>
#include <cstddef>
#include <utility>
#include <string>
#include <tuple>
using namespace std;

struct Non
{
    Non(int x, double y)
    {
        cout << x << " " << y << endl;
    }
    Non(const Non&) = delete;
    Non(Non&&) = delete;
    Non &operator=(const Non&) = delete;
    Non &operator=(Non&&) = delete;
};

template<typename T>
struct Item
{
    T item;
    
    template<typename Pack, size_t ...I>
    Item(Pack x, index_sequence<I...>)
        : item(get<I>(x)...)
    {}
    template<typename ...Args>
    Item(tuple<Args...> x)
        : Item(x, index_sequence_for<Args...>{})
    {}
};

template<typename T, typename ...Ts>
struct Tuple : Tuple<Ts...>, Item<T>
{
    using Item<T>::item;

    template<typename Pack, typename ...Tail>
    Tuple(Pack head, Tail ...tail)
        : Tuple<Ts...>(tail...), Item<T>(head)
    {}
};

template<typename T>
struct Tuple<T> : Item<T>
{
    template<typename Pack>
    Tuple(Pack head)
        : Item<T>(head)
    {}
};

int main()
{
    Tuple<string, Non, Non, Non> x{make_tuple(5, '*'), make_tuple(1, .1), make_tuple(2, .2), make_tuple(3, .3)};
    cout << x.item << endl;
    //auto y = x;// - compile error
    //auto z = move(x); - compile error
}
// Вывод:
3 0.3
2 0.2
1 0.1
*****
Отредактировано 22.09.2014 15:44 Evgeny.Panasyuk . Предыдущая версия . Еще …
Отредактировано 22.09.2014 11:13 Evgeny.Panasyuk . Предыдущая версия .
подскажите как пофиксить код
От: niXman Ниоткуда https://github.com/niXman
Дата: 21.09.14 12:51
Оценка:
снова драсте.

в продолжение темы
Автор: niXman
Дата: 21.09.14
, решил использовать найденный костыль. но загвоздка в том, что он не умеет инициализировать non-copyable и non-movable типы.
компилябельный пример:

#include <iostream>
#include <memory>
#include <utility>
#include <tuple>
#include <functional>

#include <boost/noncopyable.hpp>

/***************************************************************************/

namespace detail {
    template<int ... N>
    struct index {
        typedef index<N..., sizeof...(N)> next;
    };
    template<int N>
    struct build_index {
        typedef typename build_index<N - 1>::type::next type;
    };

    template<>
    struct build_index<0> {
        typedef index<> type;
    };

    template<typename T>
    struct tuple_index {
        typedef typename build_index<
        std::tuple_size<
        typename std::remove_reference<T>::type
        >::value
        >::type type;
    };
} // ns detail

template<typename... Elements>
class piecewise_tuple: public std::tuple<Elements...> {
    typedef std::tuple<Elements...> base_type;

    template<int Index, typename... Args, int ... N>
    static typename std::tuple_element<Index, base_type>::type
    construct(std::tuple<Args...>&& args, detail::index<N...>) {
        typedef typename std::tuple_element<Index, base_type>::type result_type;
        return result_type(std::get<N>(std::move(args))...);
    }

    template<int ...N, typename ArgTuple>
    piecewise_tuple(detail::index<N...>, ArgTuple&& element_args)
        :base_type(
            construct<N>(
                std::get<N>(std::forward<ArgTuple>(element_args))
                ,typename detail::tuple_index<
                typename std::tuple_element<
                N
                ,typename std::remove_reference<ArgTuple>::type
                >::type
                >::type()
            )...
        )
    {}

public:
    piecewise_tuple() = default;

    // For non-piecewise constructors, forward them
    template<typename... Args>
    piecewise_tuple(Args&&... args)
        :base_type(std::forward<Args>(args)...)
    {}


    template<typename... T>
    piecewise_tuple(std::piecewise_construct_t, T&&... args)
        :piecewise_tuple(
             typename detail::tuple_index<base_type>::type()
            ,std::forward_as_tuple(std::forward<T>(args)...)
        )
    {}
};

/***************************************************************************/

struct noncopyable: boost::noncopyable {};

struct type: boost::noncopyable {
    type(int &i, const char *s, noncopyable &n)
        :i(i)
        ,s(s)
        ,n(n)
    {}

    int &i;
    const char *s;
    noncopyable &n;
};

/***************************************************************************/

int main() {
   int i = 5;
    const char *s = "string";
    noncopyable n;

   std::unique_ptr<int> up(new int(0));

    piecewise_tuple<std::pair<int, int>, double, std::unique_ptr<int>, int&/*, type*/> p(
         std::piecewise_construct
        ,std::forward_as_tuple(1,2)
        ,std::forward_as_tuple(4.3)
        ,std::forward_as_tuple(std::move(up))
        ,std::forward_as_tuple(i)
        //,std::forward_as_tuple(i, s, n)
    );
}

/***************************************************************************/

тут, если расскоментить два фрагмента в main() — код перестанет компилиться. ошибка в том, что:
error: use of deleted function 'type::type(const type&)'

copy и move конструкторы для type на самом деле не нужны.

дело в том, что std::pair(std::piecewise_construct, ...) умеет что нужно.
пример конструктора std::pair() тут. но сам не могу понять, что нужно сделать.

спасибо.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Отредактировано 21.09.2014 13:17 niXman . Предыдущая версия . Еще …
Отредактировано 21.09.2014 13:05 niXman . Предыдущая версия .
Re: подскажите как пофиксить код
От: Кодт Россия  
Дата: 22.09.14 08:37
Оценка:
Здравствуйте, niXman, Вы писали:

<>
В случае с парой всё просто: размерность кортежа заранее известна, и транспонировать список пар аргументов в пару списков не составит труда.
Поэтому сразу можно сконструировать пару некопируемых-неперемещаемых типов, которая сама становится некопируемой-неперемещаемой.

А в случае с кортежом произвольной размерности — фиг.
Компилятор позволяет или сразу подставить список аргументов-скаляров в конструктор (тогда можно создать некопируемый-неперемещаемый кортеж), или должен прибегнуть к рекурсии.
А для рекурсии нужно копирование-перемещение, либо особая макросная магия — как в старом добром C++98.
Перекуём баги на фичи!
Re: подскажите как пофиксить код
От: jazzer Россия Skype: enerjazzer
Дата: 22.09.14 10:04
Оценка:
Здравствуйте, niXman, Вы писали:

X>copy и move конструкторы для type на самом деле не нужны.


Не нужны или запрещены по логике приложения?
Если не секрет, в чем проблема сделать тип перемещаемым?
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: подскажите как пофиксить код
От: niXman Ниоткуда https://github.com/niXman
Дата: 22.09.14 11:53
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Если не секрет, в чем проблема сделать тип перемещаемым?

то что я пишу — библиотечный код.
юзер будет юзать этот код, и подставлять свои type`ы. таким образом, мне, из-за кривой реализации, придется заставить юзера писать ненужный для него move-конструктор.
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
Re[3]: подскажите как пофиксить код
От: niXman Ниоткуда https://github.com/niXman
Дата: 24.09.14 19:24
Оценка:
пока сделал так:
template<typename... Types>
struct my_tuple: std::tuple<std::unique_ptr<Types>...> {
    template<typename... Args>
    my_tuple(Args&&... args)
        :std::tuple<std::unique_ptr<Types>...>(
            std::move(
                std::make_unique<Types>(std::forward<Args>(args)...)
            )...
        )
    {}
};
пачка бумаги А4 стОит 2000 р, в ней 500 листов. получается, лист обычной бумаги стОит дороже имперского рубля =)
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.