2009-12-31 9 views
5

Me pregunto si el tipo se puede determinar como información de tiempo de ejecución en C++.tiempo de ejecución determinar el tipo para C++

(1) A pesar de que mi pregunta es bastante general, para simplificar, que comenzará a partir de un ejemplo sencillo:

#include <stdio.h> 
#include <iostream> 
#include <cstring> 
using namespace std; 
int main(int argc, char * argv[]) 
{ 
if (strcmp(argv[1], "int")==0) 
{ 
    int t = 2; 
}else if (strcmp(argv[1], "float")==0) 
{ 
    float t = 2.2; 
} 
cout << t << endl; // error: ‘t’ was not declared in this scope 
return 0; 
} 

Para este ejemplo, hay dos preguntas:

(a) "argv [1] to t "es incorrecto, pero ¿la información de tipo en la cadena C argv [1] se puede convertir a la palabra clave de tipo real? Por lo tanto, no es necesario que verifiquemos cada tipo con la cláusula if-else y strcmp.

(b) cómo hacer que la variable t definida dentro del alcance local de la cláusula if aún sea válida fuera. es decir, ¿cómo "exportar" una variable local al exterior de su alcance?

(2) En general, no es específico del simple ejemplo anterior, ¿cuáles son las formas habituales de determinar los tipos de tiempo de ejecución? Me parece que podría haber algunas formas:

(a) uno puede poner su procesamiento de la variable definida del tipo dentro del mismo ámbito de su definición. p.ej.

#include <stdio.h> 
#include <iostream> 
#include <cstring> 
using namespace std; 
int main(int argc, char * argv[]) 
{ 
if (strcmp(argv[1], "int")==0) 
{ 
    int t = 2; 
    cout << t << endl; 
}else if (strcmp(argv[1], "float")==0) 
{ 
    float t = 2.2; 
    cout << t << endl; 
} 
return 0; 
} 

Y posiblemente utilice la función de plantilla para hacer que el código común para varios tipos sea reutilizable.

(b) o uno puede usar el tipo de clase abstracta y el polimorfismo para exportar indirectamente la definición, pero no estoy seguro de cómo exactamente.

Gracias por su consejo!

Respuesta

7

1a: No, los tipos no son objetos o valores en C++ (como lo son, por ejemplo, en Python). Sin embargo, puede usar varios valores seleccionados por el valor de argv [1].

1b: Lo siento, simplemente no puedo hacer eso.

2: dynamic_cast y typeid (ambos operadores) son las únicas herramientas actualmente proporcionadas por el idioma para consultar el tipo (no inusual, la mayoría de los idiomas tienen muy pocas, pero dedicadas, herramientas para eso), y usarlas únicamente para consultar el tipo a menudo se desalienta dependiendo de la situación (tampoco es inusual entre otros idiomas).

2a: Sí, y como eso es lo simple, obvio, y funciona aquí — no hay ninguna razón para usar cualquier otra cosa, pero como es un código de ejemplo, supongamos que necesita una solución diferente. Podría llamar a una plantilla de función instanciada en el tipo correcto, pero como esto es más o menos lo mismo que el resto de 2a, no entiendo.

2b: Ejemplo utilizando una plantilla subclase, sólo porque es práctico:

struct Base { 
    virtual ~Base() {} 
    friend std::ostream& operator<<(std::ostream& s, Base const& v) { 
    v._print(s); 
    return s; 
    } 
private: 
    virtual void _print(std::ostream&) const = 0; 
}; 

template<class T> 
struct Value : Base { 
    T data; 
    explicit 
    Value(T const& data) : data(data) {} 
private: 
    virtual void _print(std::ostream& s) const { 
    s << data; 
    } 
}; 

Uso:

int main(int argc, char** argv) { 
    using namespace std; 
    auto_ptr<Base> p; 
    string const type = argc > 1 ? argv[1] : "int"; 
    if (type == "int") { 
    p.reset(new Value<int>(2)); 
    } 
    else if (type == "float") { 
    p.reset(new Value<double>(2.2)); 
    } 
    cout << *p << '\n'; 
    return 0; 
} 

Esto está empezando a combinar los dos tipos en un tipo, y ambos presentan el misma interfaz, Base, aquí.Sin embargo, esto no se presta bien a todas las soluciones, y una variante como boost.variant puede ser mejor, particularmente cuando los diversos tipos requeridos son pequeños en número y se conocen con bastante antelación.

+0

+1 Iba a publicar la solución polimórfica. Tiene mucho más sentido que boost.variant porque con boost.variant deberías verificar el tipo para cada operación. –

5

Necesita una clase que sea capaz de almacenar un valor de diferentes tipos. Corto de una unión, Boost's variant class sería la elección correcta.

+0

si no usa boost? – Tim

+0

Como mencioné, una unión. –

2

Echa un vistazo Boost.Variant.

+1

Nada en la pregunta original sugiere el uso de Boost. ¿Por qué debería incluir un trabajo de cuadro completamente nuevo para una función? Lo siento, pero no veo esto como útil. –

+3

@druciferre: La pregunta pregunta cómo hacer algo en C++. Si bien muchos desarrolladores con experiencia en C++ pueden no haber escuchado acerca del impulso, deberían haberlo hecho. La pregunta ya incluye referencias al espacio de nombres estándar, la biblioteca de plantillas estándar, y se puede considerar que Boost es tan viable para usar como STL. Ahora hay muchas bibliotecas dentro de Boost, por lo que solo algunas serán significativas para un problema determinado. – jmc

Cuestiones relacionadas