Как определить кортеж типов значений из пакета параметров

Мне нужно построить кортеж из n типов. Эти n типов являются типами значений n других типов. Рассмотрим этот фрагмент:

#include <boost/hana.hpp>

namespace hana = boost::hana;

template<class... Types>
class CartesianProduct
{
public:
    CartesianProduct(Types... args) : sets(args...) {}

    hana::tuple<Types...> sets;
    hana::tuple<Types...::value_type> combination; // does not work obviously... but wo can this be done?
};

Применение этого предназначено так: я передаю этому классу пакет параметров контейнеров, возможно, разных типов. Класс помещает эти контейнеры в кортеж sets. В классе также есть поле combination, которое представляет собой кортеж из такого количества элементов, сколько контейнеров было передано в класс. Но типы элементов — это типы значений различных контейнеров.

Затем класс предназначен для ленивого построения декартова произведения переданных ему контейнеров и сохранения текущей комбинации в combination. Но как я могу на самом деле добраться до типов значений контейнеров в вариативном режиме?


person lo tolmencre    schedule 14.06.2017    source источник
comment
У всех типов есть value_type?   -  person StoryTeller - Unslander Monica    schedule 14.06.2017
comment
Ну, я делаю это предварительным условием.   -  person lo tolmencre    schedule 14.06.2017
comment
Если вы напишете этот лениво-декартовский класс продукта, было бы здорово, если бы вы могли вернуть его обратно в Hana. Я хочу добавить ленивые представления, и может быть хорошей идеей реализовать cartesian_product лениво само по себе.   -  person Louis Dionne    schedule 27.06.2017


Ответы (2)


Это можно сделать, конечно. Вам просто нужно правильно объявить расширение пакета.

hane::tuple<typename Types::value_type...> combination; 

Обратите внимание на обязательное использование спецификатора имени типа. Эмпирическое правило состоит в том, чтобы рассматривать имя пакета как один тип. Применяются те же синтаксические/семантические ограничения, поскольку мы должны указать, что мы получаем доступ к типу с оператором разрешения области видимости. Тогда просто прикрепите расширение пакета в конце.

Живой пример

#include <vector>
#include <map>
#include <tuple>

template<class... Types>
class CartesianProduct
{
public:
    CartesianProduct(Types... args) : sets(args...) {}

    std::tuple<Types...> sets;
    std::tuple<typename Types::value_type...> combination; 
};


int main() {
    std::vector<int> i;
    std::map<int, std::vector<int>> m;

    CartesianProduct<std::vector<int>, std::map<int, std::vector<int>>>
      c(i, m);

    return 0;
}
person StoryTeller - Unslander Monica    schedule 14.06.2017

Расширение правильного ответа Рассказчика (примите его ответ, пожалуйста):

Мне проще визуализировать подобные переводы типов, реализовав их с точки зрения метафункции перевода, например:

#include <vector>
#include <map>
#include <tuple>

namespace metafunction_impl
{
  // meta function taking one type (T) and 'returning' one type.
  // i.e. a unary metafunction
  template<class T> struct get_value_type
  {
    using result = typename T::value_type;
  };
}

// provide clean interface to the metafunction
template<class T> using GetValueType = typename metafunction_impl::get_value_type<T>::result;

template<class... Types>
class CartesianProduct
{
public:
    CartesianProduct(Types... args) : sets(args...) {}

    std::tuple<Types...> sets;

    // use my metafunction
    std::tuple<GetValueType<Types>...> combination; 
};


int main() {
    std::vector<int> i;
    std::map<int, std::vector<int>> m;

    CartesianProduct<std::vector<int>, std::map<int, std::vector<int>>>
      c(i, m);

    return 0;
}
person Richard Hodges    schedule 14.06.2017
comment
Это хорошая визуализация того, почему следует представлять пакет как одно имя типа. Лучше, чем мой эмпирический подход. +1 - person StoryTeller - Unslander Monica; 14.06.2017