Я хотел определить тип кортежа с переменным числом аргументов для представления координат. Например, для какого-то магического типа:
template <unsigned int N>
struct CoordT {
typedef std::tuple<_some_magic_> coord_type;
};
Я бы хотел, чтобы CoordT<3>::coord_type был трехмерным типом координат:
std::tuple<double, double, double>
.
Но я не знаю, как использовать программирование шаблонов для создания повторяющихся Ndouble.
Может ли кто-нибудь помочь объяснить, как это написать?





Используйте 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/a/7950876813128c55
Спасибо! Не могли бы вы добавить пример того, как использовать функцию foo для создания кортежа двойников?
@tinlyx проверьте ссылку coliru
Слишком поздно играть?
Если для вас приемлемо объявить (определение не требуется) функцию вариативного шаблона следующим образом
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, "!" );
}
Если вам буквально не нужен 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 и структурированные привязки.
Очень краткий способ сделать это - использовать 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, но не гарантируется. Однако в каждой реализации я проверял поддерживает это.
@Justin Хорошее замечание. Спасибо.