7

I have a function that returns a lowercase string:

constexpr auto string_to_lower_case(const std::string& string) {
    return string
        | std::views::transform(std::tolower)
        | std::views::transform([](const auto& ascii) { return static_cast<char>(ascii); });
}

and I expect that function return the same resultat when i will pass "SOME" or const std::string some("SOME"), but it's not. When I try to print out a result of string_to_lower_case("SOME"), I retrieve an empty console (the output of string_to_lower_case(some) is correct)

const std::string some("SOME");
for (const auto& ch : string_to_lower_case(some))
    std::cout << ch;
user438383
  • 5,716
  • 8
  • 28
  • 43
camelopard
  • 83
  • 1
  • 5
  • 4
    Look [here](https://stackoverflow.com/questions/63531431/passing-a-char-array-to-a-function-that-expects-a-const-stdstring-reference). The call with the char-array creates a temporary, that is gone when you want to output it – davidhigh Jun 16 '22 at 11:57
  • Your function returns a view onto the argument – M.M Jun 16 '22 at 12:30
  • Cannot reproduce in [GCC/Clang](https://godbolt.org/z/of85d4GKv). – 康桓瑋 Jun 16 '22 at 12:36
  • @康桓瑋 Add `-g -fsanitize=address,undefined` and it'll be more fun :-) – Ted Lyngmo Jun 16 '22 at 12:41

1 Answers1

7

Some issues:

  • The temporary std::string that is created when you call the function with a char[] goes out of scope when the function returns and is then destroyed. The view you return can't be used to iterate over the string after that.
  • You take the address of std::tolower which isn't allowed since it's not on the list of Designated addressable functions.
  • You don't convert the char used with std::tolower to unsigned char first. If char has a negative value, it'll cause undefined behavior.
  • Your second transformation seems redundant.

An alternative is to return an actual std::string instead of a view:

constexpr std::string string_to_lower_case(const std::string& string) {
    auto view = string
              | std::views::transform([](char ch){
                    return static_cast<char>(std::tolower(static_cast<unsigned char>(ch)));
                });
    return {view.begin(), view.end()};
}
Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108