para - sentencias en c++ pdf



¿Cómo hacer que C++ ADL vea todas las instancias de una plantilla? (1)

Agregue la declaración field_type a la plantilla de field_type , con el tipo de retorno auto (solo disponible después de C ++ 14)

Solo funciona en gcc 4.9:

#include <type_traits>

template<int N>
struct flag {
    friend constexpr int adl_flag (flag<N>);
    friend constexpr auto field_type(flag<N>);
};

template<typename T, int N>
struct writer {
    friend constexpr int adl_flag (flag<N>) { return N; }
    friend constexpr auto field_type(flag<N>) { return (T&&)(*(T*)0); }  // remove default constructable restriction
    static constexpr int value = N;
};

template<int N, class = char[noexcept(adl_flag(flag<N> ()))?+1:-1]>
int constexpr reader (int, flag<N>) { return N; }

template<int N>
int constexpr reader (float, flag<N>, int R = reader (0, flag<N-1>())) { return R; }

int constexpr reader (float, flag<0>) { return 0; }

template<typename T, int N = 1, int C = reader (0, flag<32> ())>
int constexpr next (int R = writer<T, C + N>::value) { return R; }

int main () {
    constexpr int a = next<int> ();
    constexpr int b = next<double> ();
    constexpr int c = next<long> ();

    // YES! it works!!!
    static_assert (a == 1 && b == a+1 && c == b+1, "try again");
    static_assert(std::is_same<decltype(field_type(flag<1>{})), int>{}, "first is int");
    static_assert(std::is_same<decltype(field_type(flag<2>{})), double>{}, "second is double");
    static_assert(std::is_same<decltype(field_type(flag<3>{})), long>{}, "third is long");

}

Use decltype de funciones automáticas en lugar de noexcept, funciona después de gcc 5.2, nlang 3.5.1 - 3.7.1:

#include <type_traits>

template <int N>
struct flag {
    constexpr friend auto adl_flag(flag<N>);
    friend auto field_type(flag<N>);
};

template<typename T, int N>
struct writer {
    friend constexpr auto adl_flag(flag<N>) { return 0; }
    friend auto field_type(flag<N>) { return (T&&)(*(T*)0); }
    static constexpr int value = N;
};

template<int N, class = decltype(adl_flag(flag<N>{}))>
int constexpr reader (int, flag<N>) { return N; }

template<int N>
int constexpr reader (float, flag<N>, int R = reader (0, flag<N-1>())) { return R; }

int constexpr reader (float, flag<0>) { return 0; }

template<typename T, int N = 1, int C = reader (0, flag<32> ())>
int constexpr next (int R = writer<T, C + N>::value) { return R; }

int main () {
    constexpr int a = next<int> ();
    constexpr int b = next<double> ();
    constexpr int c = next<long> ();

    // YES! it works!!!
    static_assert (a == 1 && b == a+1 && c == b+1, "try again");
    static_assert(std::is_same<decltype(field_type(flag<1>{})), int>{}, "first is int");
    static_assert(std::is_same<decltype(field_type(flag<2>{})), double>{}, "second is double");
    static_assert(std::is_same<decltype(field_type(flag<3>{})), long>{}, "third is long");

}

Estoy siguiendo Cómo implementar un contador de expresiones constantes en el tutorial de C ++ Y estoy tratando de arreglar C ++ 14 Reflexiones sin macros, marcas ni herramientas externas .

La idea básica del tutorial es esta:

template<int N>
struct flag {
  friend constexpr int adl_flag (flag<N>);
};

template<int N>
struct writer {
   friend constexpr int adl_flag (flag<N>) { return N; }
   static constexpr int value = N;
};

template<int N, class = char[noexcept(adl_flag(flag<N> ()))?+1:-1]>
int constexpr reader (int, flag<N>) { return N; }

template<int N>
int constexpr reader (float, flag<N>, int R = reader (0, flag<N-1>())) { return R; }

int constexpr reader (float, flag<0>) { return 0; }

template<int N = 1, int C = reader (0, flag<32> ())>
int constexpr next (int R = writer<C + N>::value) { return R; }

int main () {
  constexpr int a = next ();
  constexpr int b = next ();
  constexpr int c = next ();

  // YES! it works!!!
  static_assert (a == 1 && b == a+1 && c == b+1, "try again");
}

Nota: Si no está interesado por ahora, es un buen momento para dejar de leer :-)

Y la charla explica cómo extraer la cantidad de campos y tipos de campos para los tipos de POD mediante la inicialización agregada y el operador de conversión implícita, pero la limitación principal es que solo se admiten los tipos primitivos.

He proporcionado el fondo anterior para justificar mis motivaciones!

Cuando combiné estos dos enfoques llegué a esto:

template<int N>
struct flag {
  friend constexpr int adl_flag (flag<N>);
};

template<typename T, int N>
struct writer {
  friend constexpr int adl_flag (flag<N>) {
    return N;
  }
  friend constexpr T field_type(flag<N>) { return T{}; }
  static constexpr int value = N;
};

El tipo de field_type(flag<N>) me dará el tipo de campo N th. Tenga en cuenta que se trata de una función amiga y para el campo N th de un tipo POD el compilador definirá exactamente un tipo de field_type(flag<N>) .

g++ no matching function for call to 'field_type(flag<1>) me da no matching function for call to 'field_type(flag<1>) para decltype(field_type(flag<1>)) .

Necesito forzar de alguna manera a ADL para que busque en todas las instancias del writer<T,N> . ¿Cómo puedo hacer eso?

Actualizar

Como @TCmentioned ADL solo mira en las clases asociadas, y el writer no es uno. (Es por eso que adl_flag está declarado en flag - para que ADL pueda encontrarlo).

¿La pregunta es cómo hacer que el writer una clase asociada sin conocer el valor T para que ADL pueda encontrarlo?





constexpr