Comando simple para combinar un número arbitrario de valores de tipos arbitrarios en una sola cadena
Frecuentes
Visto 146 veces
0
Considere el siguiente código.
int id = 666;
stringstream stream(stringstream::in | stringstream::out);
stream << "Object " << id << " active.";
file.write(stream.str());
Combina muy bien todos los valores precedidos por << en una cadena. Me encantaría descubrir una versión más corta y fácil de usar con menos duplicación de código. Además, el código anterior es solo un ejemplo, y el comando debe aceptar combinaciones arbitrarias de variables y cadenas. Idealmente algo como:
int id = 666;
WRITE("Object ", id, " active.");
¿Es esto posible en C++? de forma portátil, incluso con Boost.Preprocessor, funciones en línea y toda la bolsa de trucos.
3 Respuestas
3
Puede lograr esto sin verificar el tipo usando una macro:
//filewrite.h
#define WRITE(first, second, third) \
{\
stringstream stream(stringstream::in | stringstream::out);\
stream << first << second << third;\
file.write(stream.str());\
}
O, más limpio, con una función de plantilla:
template<typename T1, typename T2, typename T3>
void WRITE(T1 const& first, T2 const& second, T3 const& third, fstream& file)
{
stringstream stream(stringstream::in | stringstream::out);
stream << first << second << third;
file.write(stream.str());
}
Respondido 28 ago 12, 10:08
dado el título, creo que la intención es hacerlo sin verificación de tipos, por lo tanto, no hay tipos específicos en los parámetros de su función: MartyE
Ahora, ¿alguna forma de extenderlo para tomar un número ilimitado de requisitos? - MartyE
@MartyE podría usar varargs, pero no tengo tiempo para verificar la sintaxis en este momento. - Luciano Grigore
Al usar una macro, también se pueden usar fácilmente parámetros ilimitados si el (x << y << z)
La notación se puede utilizar en el código de usuario. - Stefaanv
Los últimos dos comentarios bien podrían ser las dos respuestas correctas a mi consulta. ¡Los revisaré! - Vorac
1
Si realmente no desea la verificación de tipos, no use C ++, ¡es un lenguaje de tipado estático!
Si solo quiere decir que quiere que funcione para cualquier tipo, use una macro (eurgh) o usar plantillas variadas, algo como https://gitlab.com/redistd/redistd/blob/master/include/redi/printers.h que soporta:
#include <redi/printers.h>
using redi::println;
int main()
{
int id = 666;
println("Object ", id, " active."); // write arguments to stdout
}
El println
función toma cualquier número de argumentos y fue descaradamente robado de inspirado en un código de ejemplo de Howard Hinant.
Sería bastante fácil adaptar eso para escribir a un fstream
en lugar de std::cout
por ejemplo, agregando
inline
void
fprintln()
{ file << std::endl; }
template<typename T0, typename... T>
inline
void
fprintln(const T0& t0, const T&... t)
{
print_one(file, t0);
fprintln(t...);
}
Entonces:
fprintln("Object ", id, " active."); // write arguments to 'file'
contestado el 23 de mayo de 17 a las 13:05
1
No necesitas (ni quieres) macros. Para esto se diseñaron las plantillas:
template <typename T>
void
write( std::string const& prefix, T const& value, std::string const& suffix )
{
std::ostringstream fmt;
fmt << prefix << value << suffix;
file.write( fmt.str() );
}
Por otro lado, ¿por qué molestarse? ¿Por qué no dejar que el código del cliente use el lenguaje idiomático?
file << prefix << value << suffix;
Respondido 28 ago 12, 10:08
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas c++ c-preprocessor variadic-functions boost-preprocessor or haz tu propia pregunta.
Creo que debe ser más específico, ya que tal como está, debería poder envolver el código original en una función llamada
WRITE
. - Andreas Brinck¿Podrías hacer tu
WRITE
algo comoprintf
con el...
¿concepto? - MartyEEntonces, ¿solo quiere poner un número arbitrario de valores de tipos diferentes en el archivo? Podrías probar con una plantilla variada. - Nobody moving away from SE
Me disculpo por la pregunta muy poco clara. Intenté mejorarlo, aclarando que necesito un número variable de argumentos y que no es obligatorio usar stringstream. - Vorac
A
std::stringstream
está abierto para lectura y escritura por defecto, no hay necesidad de construirlo con(stringstream::in | stringstream::out)
- Jonathan Wakely