Simulando el rango basado en el comportamiento de inicio / fin del ciclo

Considere la especificación del rango basado en buclesbegin-expr yend-expr (N4140 [stmt.ranged] / p1). Dado un rango__range de tipo_RangeT,

begin-expr yend-expr se determinan de la siguiente manera:

Si_RangeT es un tipo de matriz,begin-expr yend-expr son__range y__range + __bound, respectivamente, donde__bound es la matriz unida. Si_RangeT es una matriz de tamaño desconocido o una matriz de tipo incompleto, el programa está mal formado;Si_RangeT es un tipo de clase, elid no calificados begin yend son buscados en el alcance de la clase_RangeT como si por la búsqueda de acceso de miembros de la clase (3.4.5), y si cualquiera (o ambos) encuentra al menos una declaración,begin-expr yend-expr son__range.begin() y__range.end(), respectivamente;de otra manera,begin-expr yend-expr sonbegin(__range) yend(__range), respectivamente, dondebegin yend se buscan en los espacios de nombres asociados (3.4.2). [Nota: La búsqueda ordinaria no calificada (3.4.1) no se realiza. -nota final ]

¿Es posible simular esto?exacto comportamiento en código C ++ ordinario? es decir, ¿podemos escribir unmagic_begin y unmagic_end plantilla de función tal que

for(auto&& p : range_init) { /* statements */ }

y

{
    auto&& my_range = range_init;
    for(auto b = magic_begin(my_range), e = magic_end(my_range); b != e; ++b){
        auto&& p = *b;
        /* statements */
    }
}

siempre tiene exactamente el mismo comportamiento?

Las no respuestas incluyen llamadas calificadas astd::begin/std::end (no maneja la tercera viñeta, entre otras cosas) yusing std::begin; begin(range); porque, entre otras cosas, eso es ambiguo si ADL parabegin encuentra una sobrecarga que es tan buena comostd::begin.

Por ejemplo, dado

namespace foo {
    struct A { int begin; }; 
    struct B { using end = int; };
    class C { int* begin(); int *end(); }; // inaccessible
    struct D { int* begin(int); int* end();};
    struct E {};

    template<class T> int* begin(T&) { return nullptr; }
    template<class T> int* end(T&) { return nullptr; }
}

foo::A a; foo::B b; foo::C c; foo::D d; foo::E e;

yo quieromagic_begin(a)/magic_begin(b)/magic_begin(c)/magic_begin(d) ser un error de compilación, ymagic_begin(e) regresar(int*)nullptr.

Respuestas a la pregunta(0)

Su respuesta a la pregunta