Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

C++ vector constructed directly as range argument not working as expected

This is different when I construct a vector directly as an argument vs. using one defined as a variable, can someone explain why?

#include <cstdlib>
#include <iostream>
#include <ostream>
#include <ranges>
#include <vector>

using namespace std;

template <std::ranges::range R>
std::ranges::borrowed_iterator_t<R> random_elt(R&& r) {
    auto it = r.begin();
    for (size_t i = 0; i < ::rand() % std::ranges::size(r); i++) {
        it++;
    }
    return it;
}

int main() {
    std::vector<int> v{1, 2, 3};

    // This is fine.
    cout << *random_elt(v) << endl;

    // Surely this should be the same?
    cout << *random_elt(std::vector<int>({1, 2, 3})) << endl;
}

Error:

$ g++ -o main main.cpp -std=gnu++23
main.cpp: In function ‘int main()’:
main.cpp:24:13: error: no match for ‘operator*’ (operand type is ‘std::ranges::borrowed_iterator_t<std::vector<int> >’)
   24 |     cout << *random_elt(std::vector<int>({1, 2, 3})) << endl;
      |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

Your function template random_elt accepts the range by reference and returns an iterator into it.

The first case is OK because the range is based on the std::vector v whose lifetime exceeds the usage of the output from random_elt.

But in the second case the argument std::vector<int>({1, 2, 3}) is a temporary. The iterator into it that you return from random_elt becomes therefore dangling, and you attempt to dereference it with operator* when the range’s lifetime has ended.

The error you posted from gcc is a bit unintuitive, but MSVC in this case issues a clearer one:

error C2100: you cannot dereference an operand of type 'std::ranges::dangling'

Live demo with MSVC error

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading