Reputation: 1741
For example:
v.for_each([](int i) { printf("%d\n", i); });
if far more elegant and readable than the commonly-used:
std::for_each(v.begin(), v.end(), [](int i) { printf("%d\n", i); });
Is there a legitimate reason such a member function is missing from the standard?
Upvotes: 5
Views: 251
Reputation: 392903
Why would you require it?
Member functions only serve the purpose if the implementation can be made more efficient (set::find is more efficient than std::find() on a set).
PS Oh, and if you want to avoid ubiquitous .begin()
, en .end()
calls, use Boost Range Algorithms. Sweet syntactic sugar
A random Boost Range inspired sample:
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/pending/integer_range.hpp>
using namespace boost::adaptors;
static int mod7(int v)
{ return v % 7; }
int main()
{
std::vector<int> v;
boost::copy(
boost::make_integer_range(1,100) | transformed(mod7),
std::back_inserter(v));
boost::sort(v);
boost::copy(
v | reversed | uniqued,
std::ostream_iterator<int>(std::cout, ", "));
}
Upvotes: 0
Reputation: 5947
template <class InputIterator, class UnaryFunction>
UnaryFunction for_each(InputIterator first, InputIterator last, UnaryFunction f);
As you can see for_each takes Input Iterator as in parameter, so any stl container that can provide a input iterator compatible(meaning apart from input iterator, it could also be bidirectional ,random access iterator etc) would be compatible with std::for_each. By designing this way, stl generic separate algorithm from data type(containers) which is more elegant & generic.
Upvotes: 2
Reputation: 146910
The simple fact is that the Standard library design is from a time when the language did not offer many features, and many designs common now, such as CRTP-based mixins, weren't around. This means that superior designs that are obvious now simply weren't implementable or designable when the Standard library was created.
Iterators make a great generic implementation, but they make a sucky generic interface. I find it saddening that instead of solving the problem with the library design and overhauling it, instead they introduced one special case language feature for one tiny subset of the problem.
Upvotes: 1
Reputation: 476970
This is the standard design rationale for the entire library: Separate containers from algorithms.
If you did it your way, you'd have to implement every feature X for every container Y, leading you to M * N implementations if you have M features and N containers.
By using iterators and make algorithms work on iterators rather than containers, you only have to implement M algorithms plus N iterator interfaces.
This separation also means that you have infinitely wider scope of application: the algorithms cannot just be used for every library container, but for any container, present or future, that anyone decides to write and equip with iterators. Finite vs infinite reuse is quite a strong argument! And calling the algorithms through the generic, free interface doesn't add any cost.
Upvotes: 8