Aunque estoy dudoso, soy curioso en cuanto a si es posible extraer primitivo-el tipo de los parámetros de la plantilla a partir de un tipo existente, tal vez usando RTTI.

Por ejemplo:

typedef std::bitset<16> WordSet;

Sería posible extraer el número 16 en el código anterior sin codificar en otro lugar? Compilador de implementaciones específicas son bienvenidos, aunque estoy particularmente interesado en la g++.

InformationsquelleAutor cdleary | 2008-11-19

5 Comentarios

  1. 41

    No es posible. La forma habitual de hacerlo es esta:

    template<int N>
    struct foo {
        static const int value = N;
    };

    y para los tipos

    template<typename T>
    struct foo {
        typedef T type;
    };

    Puede tener acceso a él, a continuación, como foo<39>::value o foo<int>::type.

    Si usted tiene un tipo particular, puede utilizar parcial de la plantilla de especialización:

    template<typename>
    struct steal_it;
    
    template<std::size_t N>
    struct steal_it< std::bitset<N> > {
        static const std::size_t value = N;
    };

    El mismo principio es posible que los parámetros de tipo demasiado, de hecho. Ahora puede pasar cualquier bitset, como steal_it< std::bitset<16> >::value (nota para utilizar size_t, no int!). Debido a que no tenemos variadic muchos plantilla de parámetros, sin embargo, nos hemos de limitar a nosotros mismos a un determinado número de parámetros, y repetir el steal_it especializaciones de plantilla para contar de 1 hasta N. Otra dificultad es analizar los tipos que se han mezclado los parámetros (tipos y no los tipos de parámetros). Esta es, probablemente, no trivial de resolver.

    Si usted no tiene el tipo, pero sólo un objeto de la misma, usted puede usar un truco, para obtener un valor en tiempo de compilación:

    template<typename T>
    char (& getN(T const &) )[steal_it<T>::value];  
    
    int main() {
        std::bitset<16> b;
        sizeof getN(b); //assuming you don't know the type, you can use the object
    }

    El truco es hacer que la plantilla de función de auto-deducir el tipo y, a continuación, devolver una referencia a una matriz de caracteres. La función no necesita ser definido, lo único que se necesita es su tipo.

    • Buen truco. Una cosa sin embargo, usted comenzar diciendo lo que no es posible, pero, a continuación, proceder a demostrar que es! 🙂
    • Corden: yo creo que él estaba diciendo es que no es posible hacer uso de RTTI
    • Richart Corden. Me refería generalmente no es posible elegir arbitrario de parámetros de plantilla. considere esto: plantilla<plantilla<clase, int> clase, clase, size_t> la clase foo; ese truco no conseguir sus tipos 🙂
  2. 5

    Usted puede hacer esto fácilmente en C++11 uso del argumento de la deducción y sin evaluar los contextos (tenga en cuenta que la demo se utiliza C++14 de variables de las características de la plantilla para mayor comodidad).

    #include <type_traits>
    #include <iostream>
    
    template<int>
    struct foo {};
    
    template<int arg_N>
    struct val {
        static constexpr auto N = arg_N;
    };
    
    template<template <int> typename T, int N>
    constexpr auto extract(const T<N>&) -> val<N>;
    
    template<typename T>
    constexpr auto extract_N = decltype(extract(std::declval<T>()))::N;
    
    
    int main() {
        std::cout << extract_N<foo<5>>;
    }

    Live demo

  3. 2

    En el caso de std::bitset, puedes usar el size() función de miembro:

    size_t sz = oh_my_word.size();  //sz is now 16

    En el caso general, se puede definir una función miembro que devuelve el tamaño de una manera similar:

    template <int N>
    class Foo
    {
    public:
      int size() const { return N; }
    };
    • Estoy hablando acerca de la extracción de terceros clases sin size() método o algo similar — extraer sólo conocer el tipo en sí. La razón es que no quiero tener que hacer un muñeco de instancia sólo para obtener el tamaño de la typedef d bitset.
    • No es un mal de la pena para el bitset, pero podría haber otros tipos en los que crear una instancia de un tipo dummy es indeseable o poco práctico.
  4. 1

    Según lo declarado por otras respuestas, para std::bitset puede obtener el tamaño mediante el uso de la size() función miembro, que debe ser la elección correcta, mejor que cualquier otro truco.

    Hubo varias propuestas para el caso genérico, casi similar a la que se sugieren a continuación, pero aún así creo que este es más simple:

    template <template<std::size_t> typename T, std::size_t K>
    auto extractSize(const T<K>&) {
        return K;
    }
    
    int main() {
        std::bitset<6> f1;
        std::bitset<13> f2;
        std::cout << extractSize(f1) << std::endl;
        std::cout << extractSize(f2) << std::endl;
    }
  5. 0

    Me gusta Marc García la respuesta de porque muestra cómo extraer el parámetro de plantilla de una manera genérica, pero yo creo que su ejemplo puede ser más simple:

    #include <type_traits>
    #include <iostream>
    
    template<int>
    struct MyType {};
    
    template<template <int> typename T, int N>
    constexpr int extract(const T<N>&) { return N; }
    
    int main() {
        constexpr MyType<5> myObj;
        std::cout << extract(myObj);
    }

    Live demo

Dejar respuesta

Please enter your comment!
Please enter your name here