Kobi
Kobi

Reputation: 878

vector of strings and transform with C++20 ranges

What is wrong in the following C++20 ranges basic syntax (Ubuntu 20.04, gcc g++ (Ubuntu 10-20200411-0ubuntu1) 10.0.1 20200411 (experimental) [master revision bb87d5cc77d:75961caccb7:f883c46b4877f637e0fa5025b4d6b5c9040ec566]):

#include <iostream>
#include <vector>
#include <ranges>

[[nodiscard]]
auto f(const std::vector<std::string>& vec) {
   return vec | std::views::transform([] (const std::string &f){ 
      return f.size(); });
}

int main() {
    const auto v = f({"c", "dddddddd", "aaaa", "bb"});
    for(auto i : v)
        std::cout << i << ' ';
    std::cout << '\n';
    return 0;
}

I'd like to take a vector of strings and transform it to the size of each string.

Trying to iterate with C++11 range for-loop is just crashing. In gdb, I can see that the std:: ranges view is pointing to invalid memory.

Dealing with non string using same constructs as above works fine.

Upvotes: 1

Views: 886

Answers (2)

bolov
bolov

Reputation: 75727

There is nothing wrong with your compiler. Your code has Undefined Behavior. Views are lazy evaluated and require that the underlying container is still alive when you access them. What you have is akin to a dangling reference.

{"c", "dddddddd", "aaaa", "bb"} Here you create a temporary vector which dies at the end of the full expression containing the call to f (a.k.a until the end of the line ;) and so it dies by the time you access v in for(auto i : v). The f.size(); from your lambda is not called until your for range loop. But at this point as I've said you temporary vector with all of its string elements don't exist anymore.

To help mitigate this kind of bug you can prohibit calling f with temporaries:

auto f(std::vector<std::string>&& vec) = delete;

Upvotes: 5

Kobi
Kobi

Reputation: 878

Seems like a 10.0.1 bug. taking Pete's example and trying it out on 10.0.1 reproduce the issue. (infinite loop) . Exact same code on https://godbolt.org/z/PqdceV 10.1 produced the desired behavior. I guess I'd need to stick to compiler explorer for now to learn ranges.

Upvotes: -2

Related Questions