Search code examples
c++variadic-templates

Correct syntax for variadic template


I'm trying to convert some ascii characters into another one. However I've been unable due to inexperience with variadic template syntax.

template<typename T>
void despecialize(const T& original, T& totransform, const int& charnum)
{
    if (static_cast<int>(totransform) == charnum) {
        totransform = original;
    }
}

template<typename T>
void despecialize(const T& original, T& totransform, const int& charnum, const int& charother...)
{
    despecialize(original, totransform, charnum);
    despecialize(original, totransform, charother...); //C3546 there are no parameter packs available to expand
}


std::string removePortugueseSpecialLetter(std::string& data)
{
    std::string transformed;
    for (auto& c : data)
    {
        despecialize('a', c, 176, 131, 132, 133, 134);
        transformed += c;
    }
    return transformed;
}

What should be the correct syntax?


Solution

  • In order to have a variadic template, you need a variadic template parameter. That looks like

    template <typename... VariadicTypeParater>
    // or
    template <some_type... VariadicNonTypeParater>
    

    Applying that to your function would give you

    template<typename T, typename... Chars>
    void despecialize(const T& original,
                      T& totransform,
                      const int& charnum,
                      const Chars&... charother)
    {
        despecialize(original, totransform, charnum);
        despecialize(original, totransform, charother...);
    }
    

    Although this will allow any type to be passed for Chars instead of just int. To constraint that you need to add SFINAE using enable_if_t non-type template parameter like

    template <typename T,
              typename... Chars,
              std::enable_if_t<(std::is_same_v<Chars, int> && ...), bool> = true>
    void despecialize(const T& original,
                      T& totransform,
                      const int& charnum,
                      const Chars& charother...)
    {
        despecialize(original, totransform, charnum);
        despecialize(original, totransform, charother...);
    }