Довольно часто в С++ 11 мне нужно определить функцию, которая принимает контейнер в качестве параметра.
Например, можно определить функцию addup (да только простая версия std::accumulate):
template <class I>
int addup (I first, I last)
{
int x = 0;
while ( first != last )
x += *first++;
return x;
}
Это принимает диапазон итераторов, который является гибким и стандартным идиомой библиотеки.
Однако предположим, что у меня есть функция:
vector<T> f();
Я должен сделать это:
auto v = f();
int x = addup(v.begin(), v.end());
Я бы скорее сделал это:
int x = addup(f());
Как я могу это сделать:
for (auto t : f())
...
В духе основанного на диапазонах я хотел бы что-то вроде этого:
template<class C>
int addup(C&& container)
{
addup(beginexpr(container), endexpr(container)); // ???
}
В стандарте говорится в 6.5.4 (перефразирование):
(A), если
container- тип массива,beginexprиendexprявляютсяcontainerиcontainer+boundсоответственно, гдеbound- это граница массива.(B), если
containerявляется типом класса, unqualified-idsbeginиendпросматриваются в области классаcontainer, как если бы поиск по элементам класса (3.4.5), и если либо (или оба) найдут хотя бы одно объявление,beginexprиendexprявляются container.begin() и container.end() соответственно;(C) в противном случае
beginexprиendexprравны соответственноbegin(container)иend(container), где начало и конец просматриваются с зависимым от аргумента поиска (3.4.2).
Можно ли определить набор перегрузок или специализаций addup, чтобы он обрабатывал четыре случая и не противоречил другим перегрузкам? Это, во-первых, регулярная функция пары итераторов, а затем каждая из A, B и C выше. Как?
(Если это возможно, то почему стандартная библиотека не предлагает такие перегрузки?)
Кроме того, что, если функция принимает дополнительные параметры за пределами контейнера? Можем ли мы модифицировать перегрузки таким образом, чтобы дополнительный добавочный параметр x (один со значением по умолчанию), добавленный ко всем из них, не делал следующие два вызова неоднозначными:
addup(v.begin(), v.end());
addup(v, x);
То есть мы можем статически утверждать (используя "SFINAE" или подобное), что параметр шаблона должен быть итератором, массивом, классом контейнера и т.д. - и использовать эту информацию для значений перегрузки?