dlr-gtlab / gt-logging

Basic C++14 logging library based on QsLog
1 stars 1 forks source link

Allow to log a range defined by iterators #137

Closed mariusalexander closed 1 month ago

mariusalexander commented 1 month ago

Sometimes I long for a simple way of iterating over a range of iterators.

Use cases

  1. A custom container class one does not want to add a dedicated overload for the operator<< (i.e. where the value type is supported by gt::log::Stream but the container class is not).
  2. Logging only a subrange instead of the whole container
  3. More customizability when it comes to logging a container. We already have implemented the gt::log::Stream::doLogIter function that does the heavy lifting, but we have "hardcoded" the separators, prefix and suffix strings for each container type we support. (e.g. std::set is logged like this: "{1, 2, 3, 4}")

Possible Implementation

We could implement a standalone function that could be used like this:

MyFancyContainer c{"A", "B", "C"};
gtDebug() << "My Fancy Range:"
          << gt::log::range(c.begin(), c.end());
// Output:
// (A, B, C)

// Alternatively: customize prefix, suffix and separator strings
gtDebug() << "My Fancy Range:" 
          << gt::log::range(c.begin(), c.end(), "range{\n ",  "\n}\n", ",\n ");
// Output:
// range{
//  A, 
//  B, 
//  C
// }

Or simply using a initlializer list/pair

MyFancyContainer c{"A", "B", "C"};
gtDebug() << "My Fancy Range:" << {c.begin(), c.end()};
// Output:
// (A, B, C)
rainman110 commented 1 month ago

I like the idea to use a range object here.

I vote against having an implicit range conversion like in

gtDebug() << "My Fancy Range:" << {c.begin(), c.end()};

as the semantics of the initializer list is not clear. It could be any object initialized with to iterators.