C++11: Defining Function With Container Parameter (like range-based for)?
c++, c++11
Solution
This is what I would do:
template<class Range>
int addup(Range&& range)
{
using std::begin;
using std::end;
addup(begin(range), end(range)); // begin(), NOT std::begin() (ADL)
}
It will handle all the important cases and does ADL properly. I'm not sure if it's equivalent to what ranged-based-for does but in my opinion it is the best solution.
the following two calls ambiguous:
I haven't compiled, but I don't see any ambiguity there unless `x` needs an implicit conversion. You can also use `boost::make_iterator_range` and avoid having an iterator parameter overload.
I think this will also work:
template<class Range>
int addup(Range&& range)
{
int x = 0;
for(auto&& v : range)
x += v;
return x;
}
template <class I>
int addup (I first, I last)
{
return addup(boost::make_iterator_range(first, last));
}
Problem
Quite frequently in C++11 I need to define a function that takes a container as a parameter. For example lets define a function `addup` (yes just a simple version of `std::accumulate`): ``` template <class I> int addup (I first, I last) { int x = 0; while ( first != last ) x += *first++; return x; } ``` This takes an iterator range, which is flexible and the standard library idiom. However suppose I have a function: ``` vector<T> f(); ``` I have to do this: ``` auto v = f(); int x = addup(v.begin(), v.end()); ``` I would rather just do this: ``` int x = addup(f()); ``` Just like I can do this: ``` for (auto t : f()) ... ``` In the spirit of range-based for I would like something like this: ``` template<class C> int addup(C&& container) { addup(beginexpr(container), endexpr(container)); // ??? } ``` In the standard it says in 6.5.4 (paraphrasing): (A) if `container` is an array type, `beginexpr` and `endexpr` are `container` and `container` + `bound`, respectively, where `bound` is the array bound. (B) if `container` is a class type, the unqualified-ids `begin` and `end` are looked up in the scope of class `container` as if by class member access lookup (3.4.5), and if either (or both) finds at least one declaration, `beginexpr` and `endexpr` are container.begin() and container.end(), respectively; (C) otherwise, `beginexpr` and `endexpr` are `begin(container)` and `end(container)`, respectively, where begin and end are looked up with argument-dependent lookup (3.4.2). Is it possible to define a set of overloads or specializations of `addup` such that it will handle the four cases, and not conflict with other overloads? That is firstly a regular iterator pair function, and then each of A, B and C above. How? (If this is possible than why doesn't the standard library offer such overloads?) Also, what if the function takes extra parameters beyond the container? Can we modify the overloads in such a way that an optional extra parameter `x` (one with a default value) added to all of them will not make the following two calls ambiguous: ``` addup(v.begin(), v.end()); addup(v, x); ``` That is can we statically assert (using "SFINAE" or similar) that the template parameter has to be an iterator, an array, a container class, etc - and have this information used for overload disambiguation?