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
containeris an array type,beginexprandendexprarecontainerandcontainer+bound, respectively, whereboundis the array bound.(B) if
containeris a class type, the unqualified-idsbeginandendare looked up in the scope of classcontaineras if by class member access lookup (3.4.5), and if either (or both) finds at least one declaration,beginexprandendexprare container.begin() and container.end(), respectively;(C) otherwise,
beginexprandendexprarebegin(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?
Range-based for loop in C++ Range-based for loop in C++ is added since C++ 11. It executes a for loop over a range. Used as a more readable equivalent to the traditional for loop operating over a range of values, such as all elements in a container.
Use the range-based for statement to construct loops that must execute through a range, which is defined as anything that you can iterate through—for example, std::vector , or any other C++ Standard Library sequence whose range is defined by a begin() and end() .
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));
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With