Começando genericamente, mais decltype, considerando a declaração de uso local
loop à distância do @ C ++ 0x tem uma exceção especial para manipular matrizes (FDIS §6.5.4), e há duas funções, std :: begin e end, que estão sobrecarregadas para manipular matrizes ou para selecionar métodos de início / fim . Isso me leva a acreditar que uma função que aceita uma sequência genérica poderia ser escrita para corresponder ao comportamento de um loop de alcance variável:
template<class C>
void f(C &c) {
using std::begin;
using std::end;
do_something_with(begin(c), end(c));
}
Se houver um início / fim "mais específico" no espaço para nome de C, ele será selecionado por meio da ADL; caso contrário, o código "usará como padrão" std :: begin / end.
No entanto, há um motivo para o qual a exceção foi especificada. Se passar uma matriz de um tipo em um espaço para nome com um início / fim semanticamente diferente que use um ponteiro, as formas de matriz de std :: begin / end não serão selecionadas:
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!
}
Para evitar isso, existe uma solução melhor do que escrever meus próprios wrappers begin / end (que usam ADL internamente) e chamá-los explicitamente em vez de std :: begin ou 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));
}
No entanto, como mostra as reticências acima, eu nem sei escrever meu :: begin! Como posso, para esse tipo de declínio, selecionar o tipo que será selecionado por meio de uma declaração de uso local e ADL?