Formatting

Some printable types support formatting. Formatting is applied with the hippo::formatter adapter, which itself is a printable type that applies a format to its contents.

Formatting numbers

The following example shows how numbers can be formatted for a user-defined type:

struct Foo {
  int bar;
  float baz;
};

static hippo::integer_format hex() {
  hippo::integer_format fmt;
  fmt.base = hippo::integer_format::base_type::hex;
  return fmt;
}

static hippo::float_format scientific() {
  hippo::float_format fmt;
  fmt.format = hippo::float_format::notation_type::scientific;
  return fmt;
};

HIPPO_CLASS_BEGIN(Foo)
  HIPPO_CLASS_MEMBER_EXPR(Foo, hippo::formatter(object.bar, hex()))
  HIPPO_CLASS_MEMBER_EXPR(Foo, hippo::formatter(object.baz, scientific()))
HIPPO_CLASS_END()

Using formatting to print polymorphic types

Polymorphic types can be printed by use of hippo::derived_type_printer:

#include "hippo/hippo.h"
#include "hippo/std/memory.h"
#include <iostream>

struct Foo {
  virtual ~Foo() = default;
};

struct Bar : Foo {};
struct Baz : Foo {};

HIPPO_CLASS_BEGIN(Foo)
HIPPO_CLASS_END()

HIPPO_CLASS_BEGIN(Bar)
  HIPPO_BASE(Foo)
HIPPO_CLASS_END()

HIPPO_CLASS_BEGIN(Baz)
  HIPPO_BASE(Foo)
HIPPO_CLASS_END()

int main() {
  std::shared_ptr<Foo> foo = std::make_shared<Foo>();
  std::shared_ptr<Foo> bar = std::make_shared<Bar>();
  std::shared_ptr<Foo> baz = std::make_shared<Baz>();
  hippo::dynamic_type_format<Foo> dyn_fmt;
  dyn_fmt.printers.push_back(std::make_shared<hippo::derived_type_printer<Foo, Bar>>());
  dyn_fmt.printers.push_back(std::make_shared<hippo::derived_type_printer<Foo, Baz>>());
  hippo::pointer_format<Foo> fmt = std::move(dyn_fmt);
  hippo::print_to(std::cout, hippo::formatter(foo, fmt), hippo::configuration());
  hippo::print_to(std::cout, hippo::formatter(bar, fmt), hippo::configuration());
  hippo::print_to(std::cout, hippo::formatter(baz, fmt), hippo::configuration());
}

Once Bar and Baz are registered with the pointer format, the printer is able to use RTTI to determine which printer to use. The following is printed:

std::shared_ptr containing [ Foo { } ]
std::shared_ptr containing [ Bar { Base Foo { } } ]
std::shared_ptr containing [ Baz { Base Foo { } } ]

Interface

template<typename T>
struct formatter

A printable type that applies formats to other printable types.

Public Types

template<>
using value_type = std::remove_const_t<T>

The type to format.

template<>
using printer_type = hippo::printer<value_type>

The printer for T

template<>
using format_type = typename printer_type::format_type

The format configuration for T

Public Functions

formatter(const value_type &value, const format_type &format)

Construct a formatter that prints value with the format described by format. The constructed formatter does not own value or format, so both must remain in scope for the lifetime of the formatter.

template<typename T>
struct formatter<T *>

Specialization of formatter for pointer types.

Public Types

template<>
using value_type = std::remove_const_t<std::decay_t<T>>

The type to format.

template<>
using printer_type = hippo::printer<value_type *>

The printer for T

template<>
using format_type = typename printer_type::format_type

The format configuration for T

Public Functions

formatter(const value_type *value, const format_type &format)

Construct a formatter that prints value with the format described by format. The constructed formatter does not own value or format, so both must remain in scope for the lifetime of the formatter.

struct no_format

Format for non-formattable types.

Number format configurations

struct integer_format

Format for integer values.

Public Types

enum base_type

Integer base description.

Values:

oct

Octal.

dec

Decimal.

hex

Hexadecimal.

Public Members

base_type base

Numeric base.

struct float_format

Format for floating-point values.

Public Types

enum notation_type

Notation format description.

Values:

standard

Format with std::defaultfloat

fixed

Format with std::fixed

scientific

Format with std::scientific

Public Members

notation_type notation

Notation format, defaults to standard

std::optional<std::size_t> precision

Precision for std::setprecision

Pointer configurations

using hippo::pointer_format = std::variant<standard_pointer_format<T>, address_format, dynamic_type_format<T>>

Format for printing a pointer.

template<typename T>
struct standard_pointer_format

Format option for non-polymorphic pointers. A non-null pointer is dereferenced and printed.

Public Types

template<>
using format_type = typename hippo::printer::format_type

Format type of T

Public Members

format_type format

The format used for printing.

struct address_format

Format option for printing pointers as addresses (rather than printing the dereferenced pointer)

template<typename T>
struct dynamic_type_format

Format option for printing polymorphic types. A non-null pointer is checked against the registered types, dereferenced, and printed.

Public Types

template<>
using base_format_type = typename hippo::printer<T>::format_type

Format type of the base class.

Public Members

std::vector<std::shared_ptr<base_type_printer<T>>> printers

Printers for derived types, in preference order.

Printers are called one by one and returns the first successful output.

base_format_type base_format

If none of the derived printers are successful, the base class is printed with this format.

template<typename Base>
struct base_type_printer

Abstract base for printers of polymorphic pointers.

Subclassed by hippo::derived_type_printer< Base, Derived >

Public Functions

virtual std::optional<hippo::object> print(const Base *b, std::uint64_t current_indent, const hippo::configuration &config) = 0

Prints b if possible, otherwise the return value is empty.

template<typename Base, typename Derived>
struct derived_type_printer : public hippo::base_type_printer<Base>

Printer for a polymorphic type from a base class pointer.

Public Types

template<>
using printer_type = hippo::printer<Derived>

Printer specialization for Derived

template<>
using format_type = typename printer_type::format_type

Format type of Derived

Public Functions

derived_type_printer()

Construct a printer using the default format.

derived_type_printer(const format_type &format)

Construct a printer using the specified format format

std::optional<hippo::object> print(const Base *b, std::uint64_t current_indent, const hippo::configuration &config)

Prints b if it is a Derived, otherwise returns nothing.