Search code examples
c++iteratorc++17ctad

Is std::make_move_iterator redundant since C++17's class template argument deduction?


Since C++11, to move append some vector y to another vector x, you can do:

x.insert(x.end(), std::make_move_iterator(y.begin()), std::make_move_iterator(y.end()));

With C++17 class template argument deduction it is possible to write this a bit more concisely:

x.insert(x.end(), std::move_iterator(y.begin()), std::move_iterator(y.end()));

From C++17 onwards, would that not make std::make_move_iterator redundant? Is there still some value in having std::make_move_iterator()?


Solution

  • Yes. One of the motivations for class template argument deduction was to avoid having to write these kinds of factory functions. In the case of move_iterator, CTAD completely subsumed the factory function. Not only does it give you all the same behavior, but it actually does one better - if the iterator you're passing in is already a move_iterator, CTAD won't give you double-wrapping whereas the factory function would.

    However, there is still going to be a lot of code that uses the factory function... so removing it would be a breaking change. But it's just obsolete, its continued existence doesn't cause anybody harm. It may eventually be deprecated.


    Note that while it is true in this case that CTAD subsumes the factory function, that is not true in the general case as the two options may have different functionality. It's not even true for all the iterator adaptors. For std::reverse_iterator(r), if r is already a reverse_iterator, will just give you a copy of r... whereas std::make_reverse_iterator(r) will re-reverse the iterator (effectively giving you back a forward iterator).