c ++ 11 — C ++ 11 — кортеж из массивов из массива кортежей

При заданном std :: tuple, например:

std::tuple<int, float, char>

Я хотел бы создать такой тип:

std::tuple<std::vector<int>, std::vector<float>, std::vector<char>>

как видите, это кортеж векторов оригинальных типов.
вот стандартный сценарий:

typedef std::tuple<int, float, char>    Struct;          // scenario 1
typedef std::vector<Struct>             ArrayOfStructs;  // scenario 2
typedef HereIsTheQuestion<Struct>::Type StructOfArrays;  // scenario 3

Сценарий 1 предназначен для доступа следующим образом:

Struct x = ...; // single tuple
std::get<0>(x) = 11;
// etc.

Сценарий 2 предназначен для доступа следующим образом:

ArrayOfStructs xs = ...; // array of tuples
for (size_t i=0; i<xs.size(); ++i) {
std::get<0>(xs[i]) = 11;
// etc.
}

Сценарий 3 предназначен для доступа следующим образом:

StructsOfArrays xs = ...; // single tuple of arrays
size_t n = std::get<0>(xs).size(); // first tuple array size
for (size_t i=0; i<n; ++i) {
std::get<0>(xs)[i] = 11;
// etc.
}

Как должен записываться HereIsTheQuestion :: Type, чтобы он напоминал кортеж массивов из исходного типа Struct?

Спасибо,
м.

2

Решение

Вот как HereIsTheQuestion должно быть реализовано.

template<typename T>       //primary template
struct HereIsTheQuestion;  //leave it undefined

template<typename ...T>
struct HereIsTheQuestion<std::tuple<T...>>  //partial specialization
{
using Type = std::tuple<std::vector<T>...>;
};

Сейчас

HereIsTheQuestion<std::tuple<int, float, char>>::Type

является

std::tuple<std::vector<int>,std::vector<float>, std::vector<char>>

Надеюсь, это поможет.

4

Другие решения

Вы можете использовать этот шаблон для создания типа:

namespace detail
{
template <typename... Ts>
struct tuple_change { };

template <typename... Ts>
struct tuple_change<std::tuple<Ts...>>
{
using type = std::tuple<std::vector<Ts>...>;
};
}

И создайте последовательность индекса следующим образом:

namespace detail
{
template <int... Is>
struct index { };

template <int N, int... Is>
struct gen_seq : gen_seq<N - 1, N - 1, Is...> { };

template <int... Is>
struct gen_seq<0, Is...> : index<Is...> { };
}

Вам также нужен шаблон, чтобы разрешить печать кортежа:

template <typename... Ts, int... Is>
static void print(std::tuple<Ts...>& var, detail::index<Is...>)
{
auto l = { (print(std::get<Is>(var)), 0)... };
(void)l;
}

template <typename... Ts>
static void print(std::tuple<Ts...>& var)
{
print(var, detail::gen_seq<sizeof...(Ts)>{});
}

template <typename T>
static void print(std::vector<T>& v)
{
for (auto a : v)
{
std::cout << std::boolalpha << a << std::endl;
}
std::cout << std::endl;
}

После этого все становится просто. Вот ваша программа:

#include <iostream>
#include <tuple>
#include <vector>

namespace detail
{
template <typename... Ts>
struct tuple_change { };

template <typename... Ts>
struct tuple_change<std::tuple<Ts...>>
{
using type = std::tuple<std::vector<Ts>...>;
};

template <int... Is>
struct index { };

template <int N, int... Is>
struct gen_seq : gen_seq<N - 1, N - 1, Is...> { };

template <int... Is>
struct gen_seq<0, Is...> : index<Is...> { };
}

template <typename... Args, int... Is>
void fill(std::tuple<Args...>& var, detail::index<Is...>)
{
auto l = { (std::get<Is>(var).assign(5, 11), 0)... };
// here I just decided to make the size 5
(void)l;
}

template <typename... Args>
void fill(std::tuple<Args...>& var)
{
fill(var, detail::gen_seq<sizeof...(Args)>{});
}

template <typename T>
static void print(std::vector<T>& v)
{
for (auto a : v)
{
std::cout << std::boolalpha << a << std::endl;
}
std::cout << std::endl;
}

template <typename... Ts, int... Is>
static void print(std::tuple<Ts...>& var, detail::index<Is...>)
{
auto l = { (print(std::get<Is>(var)), 0)... };
(void)l;
}

template <typename... Ts>
static void print(std::tuple<Ts...>& var)
{
print(var, detail::gen_seq<sizeof...(Ts)>{});
}

using result_type = detail::tuple_change<std::tuple<int, bool>>::type;

int main()
{
result_type r;

fill(r);
print(r);
}

демонстрация

3

По вопросам рекламы [email protected]