Search code examples
c++c++20std-ranges

What is the difference between std::fill_n and std::ranges::fill_n?


I'm having a hard time seeing the practical difference between std::fill_n and std::ranges::fill_n.


Solution

  • There are a few main differences that apply to all the std vs std::ranges algorithms:

    • The ones in std::ranges are constrained with concepts, so are much stricter in what they accept. It is common when migrating code using custom iterators that the iterator isn't quite an input_iterator (usually because of missing something like difference_type) so will need to be updated. The ones in std::ranges also are based on the C++20 iterator concepts, not the C++98 ones - so there are slight differences there too (most notably that you are allowed to have a forward or better iterator that gives you prvalues).

    • The ones in std::ranges are function objects, not function templates. Technically they're "niebloids", but the only way to implement them to get the required standard behavior is as a function object, and it is likely the case that they will soon be specified as such.

    Many of the algorithms have additional differences - most notably accepting a range rather than a pair of iterators. Many also have projection arguments in addition to the callables. Many also have a different return type from their std:: counterpart.

    But fill_n specifically doesn't have those extra overloads or arguments or have a distinct return type - std::ranges::fill_n is the same as std::fill_n except for the differences I laid out earlier. You can think of std::ranges::fill_n existing primarily so that every std::meow has a std::ranges::meow counterpart, so that you can wholesale switch to std::ranges without having to think about it.