Нерекурсивный tuple
От: Шахтер Интернет  
Дата: 19.05.16 06:44
Оценка: 27 (3)
Ловите

Усовершенствованная версия здесь.


/**/

template <class T>
struct IncList
 {
  template <class S>
  IncList<T> operator - (IncList<S>) { return {}; }

  using Type = T ;
 };

/**/

template <int Ind>
struct PickTypeInd
 {
  template <class T>
  PickTypeInd<Ind-1> operator - (IncList<T>) { return {}; }
 };

template <>
struct PickTypeInd<1>
 {
  template <class T>
  IncList<T> operator - (IncList<T>) { return {}; }
 };

/**/

template <int Ind,class ... TT>
using PickType = typename decltype( ( PickTypeInd<Ind>() - ... - IncList<TT>() ) )::Type ;

/**/

template <int ... IList>
struct IntList
 {
  template <class T>
  IntList<IList...,1+sizeof ... (IList)> operator + (IncList<T>) { return {}; }
 };

/**/

template <class ... TT>
struct TupleFactory
 {
  template <int Ind>
  using Type = PickType<Ind,TT...> ;

  template <int Ind>
  struct Field
   {
    Type<Ind> field;
   };

  template <int ... IList>
  struct Tuple : Field<IList>...
   {
    template <int I>
    auto & ref() { return ((Field<I> *)this)->field; }
   };

  template <int ... IList>
  static constexpr Tuple<IList...> FromList(IntList<IList...>) { return {}; }

  using Ret = decltype( FromList( ( IntList<>() + ... + IncList<TT>() ) ) ) ;
 };

template <class ... TT>
using Tuple = typename TupleFactory<TT...>::Ret ;


Вообщем, новый С++, конечно, вставляет.


Tuple<short,int,long> tuple;

tuple.ref<1>()=1;
tuple.ref<2>()=2;
tuple.ref<3>()=3;
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Отредактировано 20.05.2016 3:58 Шахтер . Предыдущая версия .
Re: Нерекурсивный tuple
От: Skorodum Россия  
Дата: 19.05.16 07:48
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Вообщем, новый С++, конечно, вставляет.


Ш>

Ш>Tuple<short,int,long> tuple;

Ш>tuple.ref<1>()=1;
Ш>tuple.ref<2>()=2;
Ш>tuple.ref<3>()=3;

Ш>


Вопрос: а где вы такое используете?

Мне в голову приходят генерация кода для ORM и сериализация данных, сетевые пакеты. Я прав?
Re: Нерекурсивный tuple
От: Went  
Дата: 19.05.16 08:09
Оценка:
Здравствуйте, Шахтер. Вообще не могу прочитать этот код. Банально не пойму где определяются переменные-члены, хранящие значения. Отстал я от жизни

P.S. Наше вроде, внутри какой-то вложенной структуры. Капец, нужно заново учиться.
Отредактировано 19.05.2016 8:11 Went . Предыдущая версия .
Re: Нерекурсивный tuple
От: PM  
Дата: 19.05.16 08:18
Оценка:
Здравствуйте, Шахтер, Вы писали:

А можно объяснить в двух словах отличия от std::tuple и чем оно лучше? Я пока вижу одно — не работает без конструктора по умолчанию:

int x;
std::tuple<int&> tuple3(x);
Tuple<int&> tuple2(x); // <-- error: no matching function for call to 'TupleFactory<int&>::Tuple<1>::Tuple(int&)'
Re[2]: Нерекурсивный tuple
От: Шахтер Интернет  
Дата: 19.05.16 08:36
Оценка:
Здравствуйте, PM, Вы писали:

PM>Здравствуйте, Шахтер, Вы писали:


PM>А можно объяснить в двух словах отличия от std::tuple и чем оно лучше? Я пока вижу одно — не работает без конструктора по умолчанию:


Оно не лучше. Это пример, демонстрирующий как можно строить tuple по-новому, без рекурсии, с использованием новых возможностей языка.
Естественно, если нужен полнофункциональный tuple, то код нужно расширять.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[2]: Нерекурсивный tuple
От: Шахтер Интернет  
Дата: 19.05.16 08:38
Оценка:
Здравствуйте, Skorodum, Вы писали:

S>Вопрос: а где вы такое используете?


Нигде, это иллюстративный пример.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[3]: Нерекурсивный tuple
От: PM  
Дата: 19.05.16 09:18
Оценка:
Здравствуйте, Шахтер, Вы писали:

PM>>А можно объяснить в двух словах отличия от std::tuple и чем оно лучше? Я пока вижу одно — не работает без конструктора по умолчанию:


Ш>Оно не лучше. Это пример, демонстрирующий как можно строить tuple по-новому, без рекурсии, с использованием новых возможностей языка.

Ш>Естественно, если нужен полнофункциональный tuple, то код нужно расширять.

Понятно. Дьявол, как обычно, в мелочах. Емнип, в libc++ тоже нерекурсивная реализация tuple
Re: Нерекурсивный tuple
От: _hum_ Беларусь  
Дата: 19.05.16 11:29
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Ловите


так а почему нерекурсивный-то, ведь "class ... TT" присутствует, значит, компилятор будет работать по рекурсии
или имелось что-то другое?
Re[2]: Нерекурсивный tuple
От: uzhas Ниоткуда  
Дата: 19.05.16 11:46
Оценка:
Здравствуйте, _hum_, Вы писали:

__>так а почему нерекурсивный-то,

рекурсивно сделано у студии:
template<class _This,
    class... _Rest>
    class tuple<_This, _Rest...>
        : private tuple<_Rest...>

то есть тупл для N элементов делается через наследование от тупла для N-1 элементов

__>ведь "class ... TT" присутствует, значит, компилятор будет работать по рекурсии

это короткая запись (см. parameter pack http://en.cppreference.com/w/cpp/language/parameter_pack ) для группы типов, тут рекурсии нет
Re: Нерекурсивный tuple
От: Кодт Россия  
Дата: 20.05.16 11:32
Оценка: 12 (1)
Здравствуйте, Шахтер, Вы писали:

Ш>Ловите


Мне кажется, что лучше, всё-таки, делать результирующие типы не using'ом зависимых имён, а наследованием.
template<class... TT> struct Tuple : typename TupleFactory<TT...>::Ret {};


Плюсы:

можно предобъявлять
// как сам тип
template<class... TT> struct Tuple;

// так и, затем, его функции доступа
template<int I, class... TT> auto get(Tuple<TT...>&       tt) -> Ref < PickType<I, TT...> >;
template<int I, class... TT> auto get(Tuple<TT...> const& tt) -> CRef< PickType<I, TT...> >;
// Ref, CRef - лень думать, как правильно пробрасывать ссылочность и константность
// для кортежей с обычными, ссылочными и константными типами компонентов


можно использовать в выведении типов
template<class... TT> void foo(Tuple<TT...> args) {}

Tuple<int,int,int> iii;
foo(iii);
Перекуём баги на фичи!
Re[2]: Нерекурсивный tuple
От: Шахтер Интернет  
Дата: 20.05.16 19:40
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Шахтер, Вы писали:


Ш>>Ловите


К>Мне кажется, что лучше, всё-таки, делать результирующие типы не using'ом зависимых имён, а наследованием.

К>
К>template<class... TT> struct Tuple : typename TupleFactory<TT...>::Ret {};
К>


Согласен, только надо унаследовать конструкторы.

template <class ... TT>
struct Tuple : TupleFactory<TT...>::Ret
 {
  using TupleFactory<TT...>::Ret::Ret;
 };
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[4]: Нерекурсивный tuple
От: Шахтер Интернет  
Дата: 20.05.16 19:43
Оценка:
Здравствуйте, PM, Вы писали:

PM>Здравствуйте, Шахтер, Вы писали:


PM>>>А можно объяснить в двух словах отличия от std::tuple и чем оно лучше? Я пока вижу одно — не работает без конструктора по умолчанию:


Ш>>Оно не лучше. Это пример, демонстрирующий как можно строить tuple по-новому, без рекурсии, с использованием новых возможностей языка.

Ш>>Естественно, если нужен полнофункциональный tuple, то код нужно расширять.

PM>Понятно. Дьявол, как обычно, в мелочах. Емнип, в libc++ тоже нерекурсивная реализация tuple


Она везде сейчас рекурсивная.
Что не есть совсем плохо, но и не очень хорошо (например, при диагностике ошибок вылезают простыни с именами всех промежуточных типов).
Хочется сделать плоскую.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[5]: Нерекурсивный tuple
От: PM  
Дата: 22.05.16 20:42
Оценка: +1
Здравствуйте, Шахтер, Вы писали:

PM>>>>А можно объяснить в двух словах отличия от std::tuple и чем оно лучше? Я пока вижу одно — не работает без конструктора по умолчанию:


Ш>>>Оно не лучше. Это пример, демонстрирующий как можно строить tuple по-новому, без рекурсии, с использованием новых возможностей языка.

Ш>>>Естественно, если нужен полнофункциональный tuple, то код нужно расширять.

PM>>Понятно. Дьявол, как обычно, в мелочах. Емнип, в libc++ тоже нерекурсивная реализация tuple


Ш>Она везде сейчас рекурсивная.

Ш>Что не есть совсем плохо, но и не очень хорошо (например, при диагностике ошибок вылезают простыни с именами всех промежуточных типов).
Ш>Хочется сделать плоскую.

Выше приведена ссылка на нерекурсивную реализацию tuple в стандартной библиотеке В boost.hana тоже нерекурcивный кортеж.

Насколько я понимаю, основное преимущество нерекурсивных раскрытий вариадиков — линейное инстанцирование шаблонов, т.е. теоретически меньшее время компиляции и потребляемый компилятором объем памяти.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.