una - C++ mismos parámetros de función con diferente tipo de retorno
tipos de parametros que se utilizan en una funcion de lenguaje c (9)
Como alternativa a la solución de plantilla, puede hacer que la función devuelva una referencia o un puntero a una clase y luego crear subclases de esa clase para que contengan los diferentes tipos de datos que desea devolver. RetrieveValue
devolvería una referencia a la subclase adecuada.
Eso permitiría que el usuario pase el objeto devuelto a otras funciones sin saber a qué subclase pertenecía.
El problema en este caso sería uno de administración de memoria: elegir qué función asigna el objeto devuelto y qué función lo elimina, y cuándo, de forma que evitemos pérdidas de memoria.
Necesito encontrar una forma de burlarme de una sobrecarga de un tipo de retorno de función en C ++.
Sé que no hay una manera de hacerlo directamente, pero espero que haya una forma de hacerlo al margen. Estamos creando una API para que los usuarios trabajen, y van a pasar una cadena de datos que recupera un valor basado en la información de la cadena. Esos valores son diferentes tipos. En esencia, nos gustaría que lo hagan:
int = RetrieveValue(dataString1);
double = RetrieveValue(dataString2);
// Obviously, since they don''t know the type, they wouldn''t use int =.... It would be:
AnotherFunction(RetrieveValue(dataString1)); // param of type int
AnotherFunction(RetrieveValue(dataString2)); // param of type double
Pero eso no funciona en C ++ (obviamente). En este momento, lo estamos configurando para que llamen:
int = RetrieveValueInt(dataString1);
double = RetrieveValueDouble(dataString2);
Sin embargo, no queremos que necesiten saber cuál es el tipo de cadena de datos.
Desafortunadamente, no tenemos permitido el uso de bibliotecas externas, así que no use Boost.
¿Hay alguna manera de evitar esto?
Solo para aclarar, entiendo que C ++ no puede hacerlo de forma nativa. Pero debe haber alguna forma de evitarlo. Por ejemplo, pensé en hacer RetrieveValue (dataString1, GetType (dataString1)). Eso realmente no arregla nada, porque GetType también solo puede tener un tipo de devolución. Pero necesito algo así.
Entiendo que esta pregunta ya se hizo antes, pero en un sentido diferente. No puedo usar ninguna de las respuestas obvias. Necesito algo completamente listo para que me sea útil, que no fue el caso con ninguna de las respuestas en la otra pregunta.
Como usaste un ejemplo que no era realmente lo que querías, echaste a todos un poco.
La configuración que realmente tiene (llamar a una función con el valor de retorno de esta función cuyo tipo de devolución es incognoscible) no funcionará porque las llamadas de función se resuelven en tiempo de compilación.
Entonces está restringido a una solución de tiempo de ejecución. Recomiendo el patrón de visitante, y tendrá que cambiar su diseño sustancialmente para permitir este cambio. Realmente no hay otra manera de hacerlo que yo pueda ver.
Desafortunadamente, no hay forma de sobrecargar el tipo de retorno de la función. Ver esta respuesta. Sobrecarga por tipo de retorno.
La única manera sensata de hacerlo es mover el valor de retorno a los parámetros.
void retrieve_value(std::string s, double& p);
void retrieve_value(std::string s, int& p);
<...>
double x;
retrieve_value(data_string1, x);
int y;
retrieve_value(data_string2, y);
Si las cadenas de datos son constantes de tiempo de compilación (como se dijo al responder a mi comentario), puede usar magia de plantilla para hacer el trabajo. Una opción aún más simple es no usar cadenas, sino algunos tipos de datos que le permiten sobrecargar el argumento.
struct retrieve_int {} as_int;
struct retrieve_double {} as_double;
int RetrieveValue(retrieve_int) { return 3; }
double RetrieveValue(retrieve_double) { return 7.0; }
auto x = RetrieveValue(as_int); // x is int
auto y = RetrieveValue(as_double); // y is double
Si sabe que su valor nunca puede ser algo así como cero o negativo, simplemente devuelva una estructura que contenga int y double y ponga a cero la que no necesita ...
Es una forma barata y sucia, pero fácil ...
struct MyStruct{
int myInt;
double myDouble;
};
MyStruct MyFunction(){
}
Tienes que comenzar con esto:
template<typename T>
T RetrieveValue(std::string key)
{
//get value and convert into T and return it
}
Para admitir esta función, debe trabajar un poco más, para convertir el valor en el tipo T
Una manera fácil de convertir el valor podría ser esta:
template<typename T>
T RetrieveValue(std::string key)
{
//get value
std::string value = get_value(key, etc);
std::stringstream ss(value);
T convertedValue;
if ( ss >> convertedValue ) return convertedValue;
else throw std::runtime_error("conversion failed");
}
Tenga en cuenta que todavía tiene que llamar a esta función como:
int x = RetrieveValue<int>(key);
Podría evitar mencionar int
dos veces, si pudiera hacer esto en su lugar:
Value RetrieveValue(std::string key)
{
//get value
std::string value = get_value(key, etc);
return { value };
}
donde Value
se implementa como:
struct Value
{
std::string _value;
template<typename T>
operator T() const //implicitly convert into T
{
std::stringstream ss(_value);
T convertedValue;
if ( ss >> convertedValue ) return convertedValue;
else throw std::runtime_error("conversion failed");
}
}
Entonces podrías escribir esto:
int x = RetrieveValue(key1);
double y = RetrieveValue(key2);
que es lo que quieres, ¿verdad?
Ya sea una sobrecarga o una especialización, necesitará que la información esté en la firma de la función. Podría pasar la variable como segundo argumento no utilizado:
int RetrieveValue(const std::string& s, const int&) {
return atoi(s.c_str());
}
double RetrieveValue(const std::string& s, const double&) {
return atof(s.c_str());
}
int i = RetrieveValue(dataString1, i);
double d = RetrieveValue(dataString2, d);
int a=itoa(retrieveValue(dataString));
double a=ftoa(retrieveValue(dataString));
ambos devuelven una cadena.