Copy and in-place transformation of strings to lowercase/uppercase I have the following code that transforms a string to upper/lowercase:

#include &lt;iterator&gt;
#include &lt;algorithm&gt;
#include &lt;type_traits&gt;
#include &lt;vector&gt;
#include &lt;vector&gt;
#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;locale&gt;
#include &lt;functional&gt;

namespace ae
{
    template &lt;typename StrT&gt;
    auto toLower(StrT&amp; str)
    {
        std::transform(str.begin(), str.end(), str.begin(), [](const auto&amp; c)
        {
            static const auto loc{ std::locale() };
            return std::tolower(c, loc);
        });
    }

    template &lt;typename StrT&gt;
    auto toUpper(StrT&amp; str)
    {
        std::transform(str.begin(), str.end(), str.begin(), [](const auto&amp; c)
        {
            static const auto loc{ std::locale() };
            return std::toupper(c, loc);
        });
    }

    template &lt;typename StrT&gt;
    auto toLowerCopy(StrT&amp; str)
    {
        auto newStr{ str };
        std::transform(str.begin(), str.end(), newStr.begin(), [](const auto&amp; c)
        {
            static const auto loc{ std::locale() };
            return std::tolower(c, loc);
        });
        return newStr;
    }

    template &lt;typename StrT&gt;
    auto toUpperCopy(StrT&amp; str)
    {
        auto newStr{ str };
        std::transform(str.begin(), str.end(), newStr.begin(), [](const auto&amp; c)
        {
            static const auto loc{ std::locale() };
            return std::toupper(c, loc);
        });
        return newStr;
    }
}

// Example usage
int main()
{
    std::wstring my_str{ L"Test" };
    ae::toLower(my_str);
    std::wcout &lt;&lt; my_str &lt;&lt; std::endl;

    std::string my_str2{ "This is a test aswell" };
    auto new_str{ ae::toUpperCopy(my_str2) };
    std::cout &lt;&lt; new_str &lt;&lt; std::endl;

    return 0;
}


All of the 4 functions are pretty much exact copies of each other, just minor variations. I dont want to repeat myself in this way, but im unsure how to make one function that does all of this functionality. How can I improve the code?
What you can do is combine the two methods toLower and toUpper into one method, say transform, to which you pass the method by which to transform (std::tolower or std::toupper) as arguments. The same can be done for toUpperCopy and toLowerCopy. Passing functions allows you to be more flexible as you are now able to not only use std::tolower and std::toupper but also any other function which transforms a character.

You can combine everything into one method and use something like a boolean parameter to tell if it should copy or not but I would advise against it. The functions are short functions so they will still be readable and you keep the responsibility for copying in a separate function.

Passing the functions would look something like this:

namespace ae
{
    template &lt;typename charT&gt;
    auto transform(std::basic_string&lt;charT&gt;&amp; str, charT charMap(charT, const std::locale&amp;))
    {
        std::transform(str.begin(), str.end(), str.begin(), [&amp;charMap](const auto&amp; c)
        {
            static const auto loc{ std::locale() };
            return charMap(c, loc);
        });
    }

    template &lt;typename charT&gt;
    auto transformCopy(std::basic_string&lt;charT&gt;&amp; str, charT charMap(charT, const std::locale&amp;))
    {
        auto newStr{ str };
        std::transform(str.begin(), str.end(), newStr.begin(), [&amp;charMap](const auto&amp; c)
        {
            static const auto loc{ std::locale() };
            return charMap(c, loc);
        });
        return newStr;
    }
}

int main()
{
    std::wstring my_str{ L"Test" };
    ae::transform(my_str, std::tolower);
    std::wcout &lt;&lt; my_str &lt;&lt; std::endl;

    std::string my_str2{ "This is a test aswell" };
    auto new_str{ ae::transformCopy(my_str2, std::toupper) };
    std::cout &lt;&lt; new_str &lt;&lt; std::endl;

    return 0;
}


Note that I changed the template variable from StrT to charT as the charT was needed for the charMap. Using both StrT and charT, the compiler was not able to infer the template argument for charT so you had to manually add the template arguments each time you called ae::transform.