Why does std::next default by 1, but std::advance does not?

  • 3
    Well, apparently because next is next and this is logical. And advance is to advance and this is not logical. - pavel
  • @pavel why then call next if it promotes to any value? - user230240
  • A similar theme, well painted link - Yura Petrov

3 answers 3

I have already made such a proposal to the C ++ Standardization Committee. I described this discrepancy in my forum in the subject std :: advance and std :: bitset - two simple sentences on the C ++ standard. The number of this sentence is # 4369 . Unfortunately, I did not follow the fate of this proposal. Formally, it was approved before the discussion, but, as always, there are people in the committee who consider only their own proposals to be the most important and jealously treat other proposals. Therefore, I now do not know what the fate of my proposal. But there are no obvious reasons for not making the default argument for the second parameter and I have not met any serious objections from other opponents.

    These functions serve somewhat different purposes and have appeared for completely different reasons.

    • std::advance is an old function (C ++ 98), which was intended to unify iterators of different categories in generic algorithms, and first of all in situations where the iterator has to be moved more than one step . With the pushing exactly one step, the operators ++ and -- coped. std::advance was executed in the form of a named function (and not operator overloading += or -= ) precisely in order to draw the user's attention to a potentially inefficient operation and thereby try to eliminate its unintended use. Similar reasons led to the appearance of the "pair" explicit function std::distance .

    • std::next and std::prev are new functions (C ++ 11), created in particular in order to encapsulate the idiom of getting a neighboring iterator without modifying the current one . Considering that, in general, a binary operation + not applicable to an iterator, you cannot simply add and add to iterator 1

       It it; ... foo(it + 1); // в общем случае - не сработает 

      For iterators of class types in such a situation, the compact version works

       foo(++It(it)); 

      but it is inapplicable to iterators of fundamental types, which in generic contexts forces to get an additional named variable, i.e. write out something like

       It it_next = it; foo(++it_next); 

      This is more cumbersome than we would like, and introduces an unnecessary named variable into the code.

      The std::advance function, if you pay attention to the features of its interface, cannot help us here. This is where the std::next and std::prev functions come to the rescue, which hide such details.

      At the same time, their most sought-after purpose / use is to get the neighboring iterator. And the ability to specify a distance is only a natural extension of this functionality.

    In other words, the answer to your question in the historical key sounds simple: std::advance was created specifically for shifting the iterator by more than 1 step , and std::next and std::prev instituted primarily for shifting exactly 1 step .

    Also, considering that std::advance can work in both directions, it would be strange now to impose +1 on it as the default argument.

    It may well be that if, initially, in C ++ 98, the std::advance function was entered with the interface

     template< class InputIt, class Distance > InputIt advance( InputIt it, Distance n ); 

    (Ie, with the transfer and return of the iterator "by value", and not with the transfer of the modified iterator "by reference"), today there would be no special need for std::next and std::prev . And if these functions would appear, it is possible without the "distance" parameter.

      Why does std::next default by 1, but std::advance does not?

      Because std::next as std::prev clearly indicate the direction of the modification. And the presence of the default value is only a refinement of the step .

      There is no sense in assigning the default modification for std::advance , since for this function the positive and negative offsets are "equal-significant". If you register a step, then it automatically equates to the residence of the default direction of the modification, which will not correspond to the abbreviation of the function.

      • 3
        Make advance offset of 0 for default, and all things :) - αλεχολυτ