В циклическом цикле C ++ 0x есть специальное исключение для обработки массивов (FDIS §6.5.4), и есть две функции, std :: begin и end, которые перегружены для обработки массивов или выбора begin / конец методы. Это наводит меня на мысль, что функция, принимающая универсальную последовательность, может быть написана так, чтобы соответствовать поведению цикла для дальней связи:
template<class C>
void f(C &c) {
using std::begin;
using std::end;
do_something_with(begin(c), end(c));
}
Если в пространстве имен C есть «более конкретное» начало / конец, оно будет выбрано через ADL, в противном случае код «по умолчанию» будет равен std :: begin / end.
Однако есть причина, по которой имеется специальное исключение. Если при передаче массива типа в пространство имен с семантически отличным началом / концом, который принимает указатель, формы массива std :: begin / end не выбираются:
namespace ns {
struct A {};
void begin(A*); // Does something completely different from std::begin.
}
void f_A() { // Imagine above f() called with an array of ns::A objects.
ns::A c[42];
using std::begin;
begin(c); // Selects ns::begin, not array form of std::begin!
}
Чтобы избежать этого, есть ли лучшее решение, чем написание моих собственных оберток начала / конца (которые используют ADL внутри) и их явный вызов вместо std :: begin или ADLized begin?
namespace my {
template<class T>
auto begin(T &c) // Also overload on T const &c, as std::begin does.
-> decltype(...) // See below.
{
using std::begin;
return begin(c);
}
template<class T, int N>
T* begin(T (&c)[N]) {
return c;
}
}
// my::end omitted, but it is analogous to my::begin.
template<class C>
void f(C &c) {
do_something_with(my::begin(c), my::end(c));
}
Однако, как показывает многоточие выше, я даже не знаю, как написать мой :: begin! Как я могу, для этого decltype, выбрать тип, который будет выбран через локальное объявление using и ADL?