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
andendexpr
arecontainer
andcontainer
+bound
, respectively, wherebound
is the array bound.(B) if
container
is a class type, the unqualified-idsbegin
andend
are looked up in the scope of classcontainer
as if by class member access lookup (3.4.5), and if either (or both) finds at least one declaration,beginexpr
andendexpr
are container.begin() and container.end(), respectively;(C) otherwise,
beginexpr
andendexpr
arebegin(container)
andend(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?