Вопрос

Consider the following code.

int id = 666;
stringstream stream(stringstream::in | stringstream::out);
stream << "Object " << id << " active.";
file.write(stream.str());

It combines all the values preceded by << in a string quite nicely. I would love to discover a shorter, easier to use version with less code duplication. Furthermore, the above code is just an example, and the command should accept arbitrary combinations of variables and strings. Ideally something like:

int id = 666;
WRITE("Object ", id, " active.");

Is this possible in C++ in a portable way, even with Boost.Preprocessor, inlined functions and all the bag of tricks.

Это было полезно?

Решение

If you really don't want type-checking don't use C++, it's a statically-typed language!

If you just mean you want it to work for any type, either use a macro (eurgh) or use variadic templates, something like https://gitlab.com/redistd/redistd/blob/master/include/redi/printers.h which supports:

#include <redi/printers.h>
using redi::println;
int main()
{
  int id = 666;
  println("Object ", id, " active.");  // write arguments to stdout
}

The println function takes any number of arguments and was shamelessly stolen from inspired by some example code from Howard Hinnant.

It would be quite easy to adapt that to write to an fstream instead of std::cout e.g. by adding

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...);
  }

Then:

 fprintln("Object ", id, " active.");  // write arguments to 'file'

Другие советы

You can accomplish this without type checking using a macro:

//filewrite.h
#define WRITE(first, second, third) \
{\
   stringstream stream(stringstream::in | stringstream::out);\
   stream << first << second << third;\
   file.write(stream.str());\
}

Or, cleaner, with a template function:

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());
}

You don't need (nor want) macros. This is what templates were designed for:

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() );
}

On the other hand, why bother? Why not just let the client code use the idiomatic:

file << prefix << value << suffix;
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top