How to convert a QVector to another with different types

95 Views Asked by At

How do I write a simple function (in C++ 17) that can get one QVector of any type, and returns a new one with converted values of any other type. For example:

auto my_function(auto in, auto f) 
{
    // ... body of function
}

// Usage:

auto my_lambda = [] (int x) { return QString::number(x); }
QVector<int> in_vector = {1,2,3};
QVector<QString> res = my_func(in_vector, my_lambda);
3

There are 3 best solutions below

2
Alex Nevskiy On BEST ANSWER

Ok, let it be something like this

template<typename F>
auto my_map(const auto &data, F f)
{
    using ReturnType = std::invoke_result_t<F, decltype(data.at(0))>;
    QVector<ReturnType> res(data.size());
    std::transform(data.begin(), data.end(), res.begin(), f);
    return res;
}

It works for non-empty vectors quite well.

UPD: Yet another working variant:

auto my_map(const auto &data, auto f)
{
    using ReturnType = decltype(f(data.at(0)));
    QVector<ReturnType> res(data.size());
    std::transform(data.begin(), data.end(), res.begin(), f);
    return res;
}
0
Swift - Friday Pie On

You're literally describing std::transform, which actually works with Qt containers (or any range-compatible containers).

If you must have exactly that signature, your function may act as an adapter for it. Because auto return type can be deduced only if you have a proper return and you still have to return SOME defined object, it's more prudent to use trailing type declaration, e.g. something like:

auto my_function(auto in, auto f) 
       -> QVector<std::remove_reference_t<decltype(f(*in.begin()))>>
{
    // do your own loop or use std::transform
}

PS. I'm just not a fan of hiding return type in function code if that's a public interface. Ofc you can declare type inside of body instead, see Alex's answer.

3
user0 On

Why don't you use a vector of QVariant? Something like QVector<QVariant> myVector, and myVector.at(0).toInt() or myVector.at(0).toString() when you need to access the data.