Printer is a stateful template functor. It captures text in an internal StringBuffer by default and can attach an explicitly supplied output stream. See header dependencies for optional standard stream support.
Capability matching and header dependencies
Printing rules inspect operations rather than specific STL template names:
- Containers expose const begin()/end() and copyable, incrementable iterators. Indexable containers use brackets.
- Map elements expose first/second; complex values expose arithmetic real()/imag() results.
- Text exposes traits_type::char_type = char and data()/size(), or converts to const char*. Ordinary character containers remain containers.
- Pointer wrappers expose get() convertible to const void*; weak wrappers expose lock() returning such a wrapper.
- Tuple protocols expose std::tuple_size<T> and ADL-accessible get<I>(const T&). Containers take precedence over tuples.
Include the headers defining your types yourself. <tuple>, <complex>, <memory>, etc. may appear before or after zeroerr/print.h, provided the types are complete before printing. Printing neither copies values nor takes ownership of smart pointers.
The print header retains its std::ostream and std::string interfaces. Stringstream management and type-name demangling live in .cpp implementations: link the zeroerr library, or define ZEROERR_IMPLEMENTATION in one translation unit when using the single header.
Construction
Printer can capture text or attach a stream supplied by the caller:
Printer();
template<class Stream> explicit Printer(Stream& os);
There are helper functions to get a global printer object that print to stdout or stderr:
extern Printer& getStdoutPrinter();
extern Printer& getStderrPrinter();
Printing Any type
A functor print(...) of the class Printer can be used to print any type variable/values.
Example:
int a = 1;
int& b = a;
int* c = &a;
print(a, b, c);
return 0;
}
Printer & getStderrPrinter()
Definition print.cpp:14
int main(int argc, const char **argv)
Definition unittest.cpp:1263
Output:
1 1 <int* at 0x7ffebc813ed4>
Function pointers print as <function-pointer-type at address>. An empty function pointer prints as nullptr. std::function prints as <wrapper-type holding target-type>, or nullptr when empty. Printing never calls the target. These values are also supported inside containers and tuples.
STL container support:
std::vector<int> vec = {1, 5, 2};
auto get_student = [](int id) {
if (id == 0) return std::make_tuple(3.8, 'A', "Lisa Simpson");
if (id == 1) return std::make_tuple(2.9, 'C', "Milhouse Van Houten");
if (id == 2) return std::make_tuple(1.7, 'D', "Ralph Wiggum");
throw std::invalid_argument("id");
};
print(a, b, c);
print({get_student(0), get_student(1), get_student(2)});
return 0;
}
Output:
[1, 5, 2]
{
(3.8, A, Lisa Simpson)
(2.9, C, Milhouse Van Houten)
(1.7, D, Ralph Wiggum)
}
Shared pointer and unique pointer:
std::shared_ptr<int> p(new int(42));
print(p);
std::unique_ptr<int> up(new int(42));
print(std::move(up));
Output:
<std::shared_ptr<int> at 0x555e1f936140>
<std::unique_ptr<int, std::default_delete<int> > at 0x555e1f931100>
Type Priority
The types are matched in the following priorities:
| level | types |
| 5 | User Customized Rules |
| 4 | std::string, std::complex, std::map |
| 3 | std::share_ptr, std::unique_ptr, std::weak_ptr, std::tuple, Array |
| 2 | container(who has begin, end methods), streamable types(with << operator), bool |
| 1 | char, wchar, POD type(need PFR library) |
| 0 | Object, C pointer, integer, float |
Configuration
The functor can be configured with different mode:
- Compact mode - everything in one line, e.g. {"a" : 1, "b" : 2}
- Colorful mode - using colorful output
- Quoted mode - string will be quoted, "a" or a for printing a string a
- Indentation - default is 2.
- Liner break - default is \n.
print.line_break = "\r\n";
Print inside stream
The printer can be used in a stream once you constructed it without giving a output stream.
Printer print;
std::cerr << print("hello world") << std::endl;
Customized Rules
You can extend the printer by creating the PrinterExt function templates, you need the following function template:
template <typename T> typename std::enable_if< <condition>, void>::type
void PrinterExt(Printer &, const T &, unsigned, const char *, rank< 0 >)
PrinterExt is an extension of Printer that allows user to write custom rules for printing.
Definition print.h:388
Here is an example for LLVM library, so you can printer pointer of llvm::Value, llvm::Type and llvm::Function:
template <typename T>
typename std::enable_if<
std::is_base_of<llvm::Value, T>::value || std::is_base_of<llvm::Type, T>::value, void>::type
PrinterExt(Printer& P, T* s,
unsigned level,
const char* lb, rank<1>) {
if (s == nullptr) {
P.os << P.tab(level) << "nullptr" << lb;
} else {
std::string text;
llvm::raw_string_ostream os(text);
s->print(os);
os.flush();
P.os << text;
}
}
template <typename T>
typename std::enable_if<std::is_base_of<llvm::Function, T>::value,
void>::type
PrinterExt(
if (s == nullptr) {
P.os << P.tab(level) << "nullptr" << lb;
} else {
std::string text;
llvm::raw_string_ostream os(text);
P.os << P.tab(level) <<
"Function " <<
FgCyan;
os << *s;
os.flush();
}
}
}
Definition assert_text.cpp:5
const char * FgCyan
Definition color.cpp:48
const char * Reset
Definition color.cpp:34
A functor class Printer for printing a value of any type.
Definition print.h:87
rank is a helper class for Printer to define the priority of overloaded functions.
Definition typetraits.h:43