String Zigzag Conversion
Don't use an alibi-class. It doesn't make the code any more OO, even in the cases it would be desirable, it just adds to the clutter.
Solution and convert are such generic names. Naming is hard, but good names really help.
You know an int need not be positive? An unsigned type may be more appropriate for a count, but even then you should handle zero.
Only if you need a null-terminated string should you consider a parameter of type std::string const&amp;. In all other cases, using std::string_view is more efficient.
While creating a temporary string of length 1 probably doesn't cause dynamic allocation due to small-string-optimisation (or allocation ellision), doing so just to add a character to the result-string is cumbersome and potentially quite inefficient (in theory, the compiler could optimise it all out). Just append it directly.
If you assign directly, diff is gone.
useDiff doesn't make a difference, so remove it.
Consider adding additional test-cases. For that, you should rewrite main().


See the modified code live on coliru:

#include &lt;string&gt;
#include &lt;string_view&gt;
#include &lt;stdexcept&gt;

auto zigzag(std::string_view s, std::size_t cRows) {
    if (!cRows)
        throw std::domain_error("Must output at least one row.");
    if (!cRows || cRows &gt;= s.size())
        return std::string(s);
    std::string r;
    r.reserve(s.size());
    const auto period = 2 * cRows - 2;
    for (auto row = 0 * cRows; row &lt; cRows; ++row) {
        auto delta = 2 * row;
        auto delta2 = period - delta;
        if (!delta) delta = period;
        if (!delta2) delta2 = period;
        for (auto i = row; i &lt; s.size(); i += delta) {
            r += s[i];
            std::swap(delta, delta2);
        }
    }
    return r;
}

#include &lt;iostream&gt;

struct test {
    std::string_view in;
    std::size_t n;
    std::string_view out;
};

int main() {
    constexpr test cases[]{
        "0123456789", 3, "0481357926",
        "", 1, "",
        "0123456789", 10, "0123456789",
        "0123456789", 2, "0246813579",
    };
    for (auto&amp;&amp; x : cases) {
        std::cout &lt;&lt; "zigzag(\"" &lt;&lt; x.in &lt;&lt; "\", " &lt;&lt; x.n &lt;&lt; ") == \"" &lt;&lt; x.out;
        auto r = zigzag(x.in, x.n);
        if (r == x.out)
            std::cout &lt;&lt; "\": PASSED\n";
        else
            std::cout &lt;&lt; "\": FAILED, got \"" &lt;&lt; r &lt;&lt; "\"\n";
    }
}