определить тип переменной (кортеж) в C ++ 17? - PullRequest
0 голосов
/ 09 января 2019

Я хотел определить тип кортежа для представления координат. Например, для некоторого магического типа:

template <unsigned int N>
struct CoordT {
  typedef std::tuple<_some_magic_> coord_type;
};

Я бы хотел, чтобы CoordT<3>::coord_type был 3-мерным типом координат:

std::tuple<double, double, double>

.

Но я не знаю, как использовать шаблонное программирование для генерации N повторных double с.

Может кто-нибудь помочь объяснить, как это написать?

Ответы [ 4 ]

0 голосов
/ 22 января 2019

Очень краткий способ сделать это - использовать std::tuple_cat и std::array:

template <unsigned int N>
struct CoordT {
  using coord_type = decltype(std::tuple_cat(std::array<double, N>{}));
};

std::tuple_cat допускается для поддержки типов, подобных кортежу , таких как std::array, но не гарантируется. Однако каждая проверенная мною реализация поддерживает это .

0 голосов
/ 09 января 2019

Слишком поздно играть?

Если для вас приемлемо объявить (определение не требуется) шаблонную функцию с переменным числом следующим образом

template <std::size_t ... Is>
constexpr auto toIndexSeq (std::index_sequence<Is...> a)
   -> decltype(a);

и что coord_type определено в специализации CoordT, вы можете написать его следующим образом

template <std::size_t N,
          typename = decltype(toIndexSeq(std::make_index_sequence<N>{}))>
struct CoordT;

template <std::size_t N, std::size_t ... Is>
struct CoordT<N, std::index_sequence<Is...>>
 { using coord_type = std::tuple<decltype((void)Is, 0.0)...>; };

Ниже приведен полный пример компиляции C ++ 14

#include <tuple> 
#include <type_traits> 

template <std::size_t ... Is>
constexpr auto toIndexSeq (std::index_sequence<Is...> a)
   -> decltype(a);

template <std::size_t N,
          typename = decltype(toIndexSeq(std::make_index_sequence<N>{}))>
struct CoordT;

template <std::size_t N, std::size_t ... Is>
struct CoordT<N, std::index_sequence<Is...>>
 { using coord_type = std::tuple<decltype((void)Is, 0.0)...>; };


int main()
 {
   using t0 = std::tuple<double, double, double, double>;
   using t1 = typename CoordT<4u>::coord_type;

   static_assert( std::is_same<t0, t1>::value, "!" );
 }
0 голосов
/ 22 января 2019

Если вам буквально не нужно std::tuple, а просто нужно что-то, что действует как кортеж, используйте std::array:

template <unsigned int N>
struct CoordT {
  typedef std::array<double, N> coord_type;
};

std::array имеет перегрузки для std::get<I>, std::tuple_size и std::tuple_element. Большинство библиотечных и языковых средств, которые принимают элемент, подобный кортежу, будут поддерживать std::array, такие как std::apply и структурированные привязки .

0 голосов
/ 09 января 2019

Используйте std::make_integer_sequence, чтобы сгенерировать пачку соответствующей длины, затем сопоставьте элементы двойным значениям:

template <size_t n>
struct TupleOfDoubles {
    template <size_t... i>
    static auto foo(std::index_sequence<i...>) {
        return std::make_tuple(double(i)...);
    }
    using type = decltype(foo(std::make_index_sequence<n>{}));
};

http://coliru.stacked -crooked.com / а / 7950876813128c55

...