c++qtqstring

Is there an efficient way to pass a list of args to a QString, by avoiding copies?


Lets say I have a list of N arguments which I want to pass to a QString. The number N is variable and determined at runtime.

If I do this:

QString myString = "Some text %1, some other text %2,..., some more text %n"
for(auto arg : list) {
  myString = myString.arg(arg);
}

I create a lot of string copies, as I can only change one .arg at a time, and need to save one copy of the string in each iteration. Is there a more efficient way? I looked into the documentation for something like QString::args(SomethingIteratable), but found nothing.


Solution

  • With some hard-coded limit (to transform runtime vector size to compile time one), you might use arg() overload taking several QString

    std::variant<
        std::integral_constant<std:size_t, 1>,
        std::integral_constant<std:size_t, 2>
        std::integral_constant<std:size_t, 3>
        std::integral_constant<std:size_t, 4>
        std::integral_constant<std:size_t, 5>
        // Adapt to your limit
        >
    as_integral_constant(std::size_t n) {
        switch (n) {
            case 1: return std::integral_constant<std:size_t, 1>{};
            case 2: return std::integral_constant<std:size_t, 2>{};
            case 3: return std::integral_constant<std:size_t, 3>{};
            case 4: return std::integral_constant<std:size_t, 4>{};
            case 5: return std::integral_constant<std:size_t, 5>{};
            // adapt to your limit...
        }
        throw std::runtime_error("Unsupported size");
    }
    

    And then, visit:

    QString args(QString format, const std::vector<QString>& list)
    {
        const auto size = as_integral_constant(list.size());
        return std::visit([&](auto N){
            return [&]<std::size_t... Is>(std::index_sequence<Is...>) {
                return format.arg(list[Is]...);
            }(std::make_index_sequence<N()>());
        }, size);
    }
    

    Notice than arg in one pass might behave differently than multipass, especially if your inserted texts contain %1.