Home > Blockchain >  c 20 template parameter of random_access_iterator concept, cannot accept iterator type?
c 20 template parameter of random_access_iterator concept, cannot accept iterator type?

Time:08-02

For c 20 concept, I had a quick test:

#include<iostream>
#include<vector>
using namespace std;

template <random_access_iterator I>
void advance(I &iter, int n) {
    cout << "random_access_iterator" << '\n';
}
int main() {
    vector vec{1, 2, 3};
    {
        vector<int>::iterator itRa = vec.begin();
        advance(itRa, 2);
    }
    advance(vec.begin(), 3); // compilation error!
    return 0;
}

I run clang 14 on windows10 and it prints:

clang   .\MyAdvance.cpp -std=c  20
candidate function [with _InIt =
      std::_Vector_iterator<std::_Vector_val<std::_Simple_types<int>>>, _Diff =   
      int] not viable: expects an lvalue for 1st argument
_CONSTEXPR17 void advance(_InIt& _Where, _Diff _Off) { // increment iterat...     
                  ^
.\MyAdvance.cpp:6:6: note: candidate function [with I =
      std::_Vector_iterator<std::_Vector_val<std::_Simple_types<int>>>] not       
      viable: expects an lvalue for 1st argument
void advance(I &iter, int n) {
     ^
1 error generated.

Very strange, what's the difference between:

vector<int>::iterator itRa = vec.begin();
advance(itRa, 2);

and

advance(vec.begin(), 3); // compilation error!

Why the 1st version gets compiled and 2nd version doesn't?

CodePudding user response:

begin() returns an iterator by-value, meaning the call expression is a prvalue. You can't pass a prvalue as an argument to a non-const lvalue reference parameter. That is not specific to iterators. It applies to any type, e.g.

void f(int&);

//...

f(1234); // fails because 1234 is a prvalue

To allow for prvalues as argument as well you would need to add another overload with I&& instead of I& argument type:

template <random_access_iterator I>
void advance(I &&iter, int n) {
    cout << "random_access_iterator" << '\n';
}

But that doesn't really make sense. Why should it be allowed to advance an iterator which is then immediately destroyed? If someone writes advance(vec.begin(), 3) then that must be a mistake and it is good that it produces an error since that expression has no effect at all.

  • Related