Начиная в общем, плюс decltype с учетом локального объявления-использования

Цикл ранжирования C ++ 0x имеет специальное исключение для обработки массивов (FDIS §6.5.4), и есть две функции, std :: begin и end, которые перегружены для обработки массивов или для выберите методы начала / завершения. Это наводит меня на мысль, что функция, принимающая универсальную последовательность, может быть написана так, чтобы соответствовать поведению ранжированного цикла:

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.

Однако есть причина, по которой ranged-for имеет это специальное исключение. При передаче массива типа в пространстве имен с семантически другим началом / концом, которое принимает указатель, формы массива 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!
}

Чтобы избежать этого, есть ли лучший решение, чем писать свои собственные оболочки begin / end (которые используют 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 выбрать тип, который будет выбран с помощью локального объявления-использования и ADL?

11
задан Fred Nurk 30 May 2011 в 19:00
поделиться