C++:Convert Vector to Tuple

With C++-17, how to populate a tuple from a vector of string

It is impossible to map the value of a std::string input to multiple types, as the value is only known at run-time.

The best you can do is create a tuple out of the vector, provided you know its size at compile-time:

template <std::size_t... Is>
auto create_tuple_impl(std::index_sequence<Is...>, const std::vector<std::string>& arguments) {
return std::make_tuple(arguments[Is]...);
}

template <std::size_t N>
auto create_tuple(const std::vector<std::string>& arguments) {
return create_tuple_impl(std::make_index_sequence<N>{}, arguments);
}

Usage:

const std::vector<std::string> inputs{"100", "42.22"};
const auto t = create_tuple<2>(inputs);

live example on godbolt.org


EDIT: if you want to select the types manually:

template<class T> T transform_arg(std::string const &s);
template<> double transform_arg(std::string const &s) { return atof(s.c_str());}
template<> int transform_arg(std::string const &s) { return atoi(s.c_str());}

template <typename... Args, std::size_t... Is>
auto create_tuple_impl(std::index_sequence<Is...>, const std::vector<std::string>& arguments) {
return std::make_tuple(transform_arg<Args>(arguments[Is])...);
}

template <typename... Args>
auto create_tuple(const std::vector<std::string>& arguments) {
return create_tuple_impl<Args...>(std::index_sequence_for<Args...>{}, arguments);
}

Usage:

const std::vector<std::string> inputs{"100", "42.22", "11"};
const auto t = create_tuple<int, double, int>(inputs);

static_assert(std::is_same_v<decltype(t), const std::tuple<int, double, int>>);

live example on godbolt.org

Can I convert an std::vector into an std::tuple at runtime?

You cannot. A tuple is a compile-time container which contains a certain number of elements. This means that the code that handles a tuple is generated at compile time, and is dependent on the number of elements that you specified for the tuple.

At the same time, this will also be true for the function you are calling: you will be able to call it only with a specific type of tuple. Passing a reference to the vector you already have seems a better solution.

How to create a tuple of vectors of type deduced from a variadic template in C++17?

You're using C++17 so... what about using template folding and some std::apply()?

I mean

template <typename ... Ts>
class Collection
{
private:
std::tuple<std::vector<Ts>...> m_col;

public:
void addRow (std::tuple<Ts...> const & data)
{
std::apply([&](auto & ... vectors){
std::apply([&](auto & ... values){
(vectors.push_back(values), ...);},
data); },
m_col);
}

void show () const
{
std::apply([](auto & ... vectors){
((std::cout << vectors.size() << '\n'), ...);}, m_col);
}
};

Dynamically construct tuple from vector

Of course it can only be done at compile-time: the "members" of a tuple are baked into its type.

What is the most efficient way of converting a std::vectorstd::tuple to a torch::Tensor?

I am not aware of any libtorch feature to do that easily. I would have suggested to use torch::from_blob, hoping for the data to be stored contiguously, but I have found this thread that says otherwise.

So if possible, my suggestion would be to replace your tuple<float, float...>by std::array<float, 4> (for which memory layout is contiguous), and do something like

std::vector<std::array<float,4>> anchors_raw;
// ...
auto options = torch::TensorOptions().dtype(at::kFloat);
auto anchors = torch::from_blob(&anchors_raw[0][0], {anchors_raw.size(), 4}, options).clone()

I cannot try it at the moment so I hope it compiles and run fine, but I believe it should work, all float values should be stored contiguously in the vector and the arrays, so from_blobwill work.

As always, the call to clone is required if anchors_raw is at risk of going out of scope before you're done with anchors. If you're sure anchors_raw will outlive anchors, you can remove the call.



Related Topics



Leave a reply



Submit