www.mooseframework.org
Public Types | Public Member Functions | Protected Member Functions | Static Protected Member Functions | Protected Attributes | List of all members
VariadicTable< Ts > Class Template Reference

A class for "pretty printing" a table of data. More...

#include <PerfGraph.h>

Public Types

typedef std::tuple< Ts... > DataTuple
 The type stored for each row. More...
 

Public Member Functions

 VariadicTable (std::vector< std::string > headers, unsigned int static_column_size=0, unsigned int cell_padding=1)
 Construct the table with headers. More...
 
void addRow (Ts... entries)
 Add a row of data. More...
 
template<typename StreamType >
void print (StreamType &stream)
 Pretty print the table of data. More...
 
void setColumnFormat (const std::vector< VariadicTableColumnFormat > &column_format)
 Set how to format numbers for each column. More...
 
void setColumnPrecision (const std::vector< int > &precision)
 Set how many digits of precision to show for floating point numbers. More...
 

Protected Member Functions

template<typename TupleType , typename StreamType >
void print_each (TupleType &&, StreamType &, std::integral_constant< size_t, std::tuple_size< typename std::remove_reference< TupleType >::type >::value >)
 These three functions print out each item in a Tuple into the table. More...
 
template<std::size_t I, typename TupleType , typename StreamType , typename = typename std::enable_if< I != std::tuple_size<typename std::remove_reference<TupleType>::type>::value>::type>
void print_each (TupleType &&t, StreamType &stream, std::integral_constant< size_t, I >)
 This gets called on each item. More...
 
template<typename TupleType , typename StreamType >
void print_each (TupleType &&t, StreamType &stream)
 his is what gets called first More...
 
template<class T >
size_t sizeOfData (const T &data, decltype(((T *) nullptr) ->size()) *=nullptr)
 Try to find the size the column will take up. More...
 
template<class T >
size_t sizeOfData (const T &data, typename std::enable_if< std::is_integral< T >::value >::type *=nullptr)
 Try to find the size the column will take up. More...
 
size_t sizeOfData (...)
 If it doesn't... More...
 
template<typename TupleType >
void size_each (TupleType &&, std::vector< unsigned int > &, std::integral_constant< size_t, std::tuple_size< typename std::remove_reference< TupleType >::type >::value >)
 These three functions iterate over the Tuple, find the printed size of each element and set it in a vector. More...
 
template<std::size_t I, typename TupleType , typename = typename std::enable_if< I != std::tuple_size<typename std::remove_reference<TupleType>::type>::value>::type>
void size_each (TupleType &&t, std::vector< unsigned int > &sizes, std::integral_constant< size_t, I >)
 Recursively called for each element. More...
 
template<typename TupleType >
void size_each (TupleType &&t, std::vector< unsigned int > &sizes)
 The function that is actually called that starts the recursion. More...
 
void size_columns ()
 Finds the size each column should be and set it in _column_sizes. More...
 

Static Protected Member Functions

template<typename T , typename = typename std::enable_if< std::is_arithmetic<typename std::remove_reference<T>::type>::value>::type>
static right_type justify (int)
 
template<typename T >
static left_type justify (long)
 

Protected Attributes

decltype(&std::right) typedef right_type
 
decltype(&std::left) typedef left_type
 
std::vector< std::string > _headers
 The column headers. More...
 
unsigned int _num_columns
 Number of columns in the table. More...
 
unsigned int _static_column_size
 Size of columns that we can't get the size of. More...
 
unsigned int _cell_padding
 Size of the cell padding. More...
 
std::vector< DataTuple_data
 The actual data. More...
 
std::vector< unsigned int > _column_sizes
 Holds the printable width of each column. More...
 
std::vector< VariadicTableColumnFormat_column_format
 Column Format. More...
 
std::vector< int > _precision
 Precision For each column. More...
 

Detailed Description

template<class... Ts>
class VariadicTable< Ts >

A class for "pretty printing" a table of data.

Requries C++11 (and nothing more)

It's templated on the types that will be in each column (all values in a column must have the same type)

For instance, to use it with data that looks like: "Fred", 193.4, 35, "Sam" with header names: "Name", "Weight", "Age", "Brother"

You would invoke the table like so: VariadicTable<std::string, double, int, std::string> vt("Name", "Weight", "Age", "Brother");

Then add the data to the table: vt.addRow("Fred", 193.4, 35, "Sam");

And finally print it: vt.print();

Definition at line 27 of file PerfGraph.h.

Member Typedef Documentation

◆ DataTuple

template<class... Ts>
typedef std::tuple<Ts...> VariadicTable< Ts >::DataTuple

The type stored for each row.

Definition at line 57 of file VariadicTable.h.

Constructor & Destructor Documentation

◆ VariadicTable()

template<class... Ts>
VariadicTable< Ts >::VariadicTable ( std::vector< std::string >  headers,
unsigned int  static_column_size = 0,
unsigned int  cell_padding = 1 
)
inline

Construct the table with headers.

Parameters
headersThe names of the columns
static_column_sizeThe size of columns that can't be found automatically

Definition at line 65 of file VariadicTable.h.

68  : _headers(headers),
69  _num_columns(std::tuple_size<DataTuple>::value),
70  _static_column_size(static_column_size),
71  _cell_padding(cell_padding)
72  {
73  assert(headers.size() == _num_columns);
74  }
unsigned int _cell_padding
Size of the cell padding.
unsigned int _num_columns
Number of columns in the table.
unsigned int _static_column_size
Size of columns that we can&#39;t get the size of.
std::vector< std::string > _headers
The column headers.

Member Function Documentation

◆ addRow()

template<class... Ts>
void VariadicTable< Ts >::addRow ( Ts...  entries)
inline

Add a row of data.

Easiest to use like: table.addRow({data1, data2, data3});

Parameters
dataA Tuple of data to add

Definition at line 84 of file VariadicTable.h.

Referenced by PerfGraph::recursivelyPrintGraph(), and PerfGraph::recursivelyPrintHeaviestGraph().

84 { _data.emplace_back(std::make_tuple(entries...)); }
std::vector< DataTuple > _data
The actual data.

◆ justify() [1/2]

template<class... Ts>
template<typename T , typename = typename std::enable_if< std::is_arithmetic<typename std::remove_reference<T>::type>::value>::type>
static right_type VariadicTable< Ts >::justify ( int  )
inlinestaticprotected

Definition at line 171 of file VariadicTable.h.

172  {
173  return std::right;
174  }

◆ justify() [2/2]

template<class... Ts>
template<typename T >
static left_type VariadicTable< Ts >::justify ( long  )
inlinestaticprotected

Definition at line 178 of file VariadicTable.h.

179  {
180  return std::left;
181  }

◆ print()

template<class... Ts>
template<typename StreamType >
void VariadicTable< Ts >::print ( StreamType &  stream)
inline

Pretty print the table of data.

Definition at line 90 of file VariadicTable.h.

91  {
92  size_columns();
93 
94  // Start computing the total width
95  // First - we will have _num_columns + 1 "|" characters
96  unsigned int total_width = _num_columns + 1;
97 
98  // Now add in the size of each colum
99  for (auto & col_size : _column_sizes)
100  total_width += col_size + (2 * _cell_padding);
101 
102  // Print out the top line
103  stream << std::string(total_width, '-') << "\n";
104 
105  // Print out the headers
106  stream << "|";
107  for (unsigned int i = 0; i < _num_columns; i++)
108  {
109  // Must find the center of the column
110  auto half = _column_sizes[i] / 2;
111  half -= _headers[i].size() / 2;
112 
113  stream << std::string(_cell_padding, ' ') << std::setw(_column_sizes[i]) << std::left
114  << std::string(half, ' ') + _headers[i] << std::string(_cell_padding, ' ') << "|";
115  }
116 
117  stream << "\n";
118 
119  // Print out the line below the header
120  stream << std::string(total_width, '-') << "\n";
121 
122  // Now print the rows of the table
123  for (auto & row : _data)
124  {
125  stream << "|";
126  print_each(row, stream);
127  stream << "\n";
128  }
129 
130  // Print out the line below the header
131  stream << std::string(total_width, '-') << "\n";
132  }
unsigned int _cell_padding
Size of the cell padding.
std::vector< DataTuple > _data
The actual data.
unsigned int _num_columns
Number of columns in the table.
void print_each(TupleType &&, StreamType &, std::integral_constant< size_t, std::tuple_size< typename std::remove_reference< TupleType >::type >::value >)
These three functions print out each item in a Tuple into the table.
std::vector< unsigned int > _column_sizes
Holds the printable width of each column.
std::vector< std::string > _headers
The column headers.
void size_columns()
Finds the size each column should be and set it in _column_sizes.

◆ print_each() [1/3]

template<class... Ts>
template<typename TupleType , typename StreamType >
void VariadicTable< Ts >::print_each ( TupleType &&  ,
StreamType &  ,
std::integral_constant< size_t, std::tuple_size< typename std::remove_reference< TupleType >::type >::value >   
)
inlineprotected

These three functions print out each item in a Tuple into the table.

Original Idea From From https://stackoverflow.com/a/26908596

BTW: This would all be a lot easier with generic lambdas there would only need to be one of this sequence and then you could pass in a generic lambda. Unfortunately, that's C++14 This ends the recursion

Definition at line 197 of file VariadicTable.h.

Referenced by VariadicTable< Ts >::print(), and VariadicTable< Ts >::print_each().

202  {
203  }

◆ print_each() [2/3]

template<class... Ts>
template<std::size_t I, typename TupleType , typename StreamType , typename = typename std::enable_if< I != std::tuple_size<typename std::remove_reference<TupleType>::type>::value>::type>
void VariadicTable< Ts >::print_each ( TupleType &&  t,
StreamType &  stream,
std::integral_constant< size_t, I >   
)
inlineprotected

This gets called on each item.

Definition at line 213 of file VariadicTable.h.

214  {
215  auto & val = std::get<I>(t);
216 
217  // Set the precision
218  if (!_precision.empty())
219  {
220  assert(_precision.size() ==
222 
223  stream << std::setprecision(_precision[I]);
224  }
225 
226  // Set the format
227  if (!_column_format.empty())
228  {
229  assert(_column_format.size() ==
231 
233  stream << std::scientific;
234 
236  stream << std::fixed;
237 
239  stream << std::fixed << std::setprecision(2);
240  }
241 
242  stream << std::string(_cell_padding, ' ') << std::setw(_column_sizes[I])
243  << justify<decltype(val)>(0) << val << std::string(_cell_padding, ' ') << "|";
244 
245  // Unset the format
246  if (!_column_format.empty())
247  {
248  // Because "stream << std::defaultfloat;" won't compile with old GCC or Clang
249  stream.unsetf(std::ios_base::floatfield);
250  }
251 
252  // Recursive call to print the next item
253  print_each(std::forward<TupleType>(t), stream, std::integral_constant<size_t, I + 1>());
254  }
std::vector< int > _precision
Precision For each column.
unsigned int _cell_padding
Size of the cell padding.
std::vector< VariadicTableColumnFormat > _column_format
Column Format.
void print_each(TupleType &&, StreamType &, std::integral_constant< size_t, std::tuple_size< typename std::remove_reference< TupleType >::type >::value >)
These three functions print out each item in a Tuple into the table.
MatType type
std::vector< unsigned int > _column_sizes
Holds the printable width of each column.

◆ print_each() [3/3]

template<class... Ts>
template<typename TupleType , typename StreamType >
void VariadicTable< Ts >::print_each ( TupleType &&  t,
StreamType &  stream 
)
inlineprotected

his is what gets called first

Definition at line 260 of file VariadicTable.h.

261  {
262  print_each(std::forward<TupleType>(t), stream, std::integral_constant<size_t, 0>());
263  }
void print_each(TupleType &&, StreamType &, std::integral_constant< size_t, std::tuple_size< typename std::remove_reference< TupleType >::type >::value >)
These three functions print out each item in a Tuple into the table.

◆ setColumnFormat()

template<class... Ts>
void VariadicTable< Ts >::setColumnFormat ( const std::vector< VariadicTableColumnFormat > &  column_format)
inline

Set how to format numbers for each column.

Note: this is ignored for std::string columns

The format for each column: MUST be the same length as the number of columns.

Definition at line 141 of file VariadicTable.h.

Referenced by PerfGraph::print(), PerfGraph::printHeaviestBranch(), and PerfGraph::printHeaviestSections().

142  {
143  assert(column_format.size() == std::tuple_size<DataTuple>::value);
144 
145  _column_format = column_format;
146  }
std::vector< VariadicTableColumnFormat > _column_format
Column Format.

◆ setColumnPrecision()

template<class... Ts>
void VariadicTable< Ts >::setColumnPrecision ( const std::vector< int > &  precision)
inline

Set how many digits of precision to show for floating point numbers.

Note: this is ignored for std::string columns

The precision for each column: MUST be the same length as the number of columns.

Definition at line 155 of file VariadicTable.h.

156  {
157  assert(precision.size() == std::tuple_size<DataTuple>::value);
158  _precision = precision;
159  }
std::vector< int > _precision
Precision For each column.

◆ size_columns()

template<class... Ts>
void VariadicTable< Ts >::size_columns ( )
inlineprotected

Finds the size each column should be and set it in _column_sizes.

Definition at line 346 of file VariadicTable.h.

Referenced by VariadicTable< Ts >::print().

347  {
348  _column_sizes.resize(_num_columns);
349 
350  // Temporary for querying each row
351  std::vector<unsigned int> column_sizes(_num_columns);
352 
353  // Start with the size of the headers
354  for (unsigned int i = 0; i < _num_columns; i++)
355  _column_sizes[i] = _headers[i].size();
356 
357  // Grab the size of each entry of each row and see if it's bigger
358  for (auto & row : _data)
359  {
360  size_each(row, column_sizes);
361 
362  for (unsigned int i = 0; i < _num_columns; i++)
363  _column_sizes[i] = std::max(_column_sizes[i], column_sizes[i]);
364  }
365  }
void size_each(TupleType &&, std::vector< unsigned int > &, std::integral_constant< size_t, std::tuple_size< typename std::remove_reference< TupleType >::type >::value >)
These three functions iterate over the Tuple, find the printed size of each element and set it in a v...
std::vector< DataTuple > _data
The actual data.
unsigned int _num_columns
Number of columns in the table.
std::vector< unsigned int > _column_sizes
Holds the printable width of each column.
std::vector< std::string > _headers
The column headers.

◆ size_each() [1/3]

template<class... Ts>
template<typename TupleType >
void VariadicTable< Ts >::size_each ( TupleType &&  ,
std::vector< unsigned int > &  ,
std::integral_constant< size_t, std::tuple_size< typename std::remove_reference< TupleType >::type >::value >   
)
inlineprotected

These three functions iterate over the Tuple, find the printed size of each element and set it in a vector.

End the recursion

Definition at line 305 of file VariadicTable.h.

Referenced by VariadicTable< Ts >::size_columns(), and VariadicTable< Ts >::size_each().

310  {
311  }

◆ size_each() [2/3]

template<class... Ts>
template<std::size_t I, typename TupleType , typename = typename std::enable_if< I != std::tuple_size<typename std::remove_reference<TupleType>::type>::value>::type>
void VariadicTable< Ts >::size_each ( TupleType &&  t,
std::vector< unsigned int > &  sizes,
std::integral_constant< size_t, I >   
)
inlineprotected

Recursively called for each element.

Definition at line 321 of file VariadicTable.h.

322  {
323  sizes[I] = sizeOfData(std::get<I>(t));
324 
325  // Override for Percent
326  if (!_column_format.empty())
328  sizes[I] = 6; // 100.00
329 
330  // Continue the recursion
331  size_each(std::forward<TupleType>(t), sizes, std::integral_constant<size_t, I + 1>());
332  }
void size_each(TupleType &&, std::vector< unsigned int > &, std::integral_constant< size_t, std::tuple_size< typename std::remove_reference< TupleType >::type >::value >)
These three functions iterate over the Tuple, find the printed size of each element and set it in a v...
size_t sizeOfData(const T &data, decltype(((T *) nullptr) ->size()) *=nullptr)
Try to find the size the column will take up.
std::vector< VariadicTableColumnFormat > _column_format
Column Format.

◆ size_each() [3/3]

template<class... Ts>
template<typename TupleType >
void VariadicTable< Ts >::size_each ( TupleType &&  t,
std::vector< unsigned int > &  sizes 
)
inlineprotected

The function that is actually called that starts the recursion.

Definition at line 338 of file VariadicTable.h.

339  {
340  size_each(std::forward<TupleType>(t), sizes, std::integral_constant<size_t, 0>());
341  }
void size_each(TupleType &&, std::vector< unsigned int > &, std::integral_constant< size_t, std::tuple_size< typename std::remove_reference< TupleType >::type >::value >)
These three functions iterate over the Tuple, find the printed size of each element and set it in a v...

◆ sizeOfData() [1/3]

template<class... Ts>
template<class T >
size_t VariadicTable< Ts >::sizeOfData ( const T &  data,
decltype(((T *) nullptr) ->size()) *  = nullptr 
)
inlineprotected

Try to find the size the column will take up.

If the datatype has a size() member... let's call it

Definition at line 271 of file VariadicTable.h.

Referenced by VariadicTable< Ts >::size_each().

272  {
273  return data.size();
274  }

◆ sizeOfData() [2/3]

template<class... Ts>
template<class T >
size_t VariadicTable< Ts >::sizeOfData ( const T &  data,
typename std::enable_if< std::is_integral< T >::value >::type = nullptr 
)
inlineprotected

Try to find the size the column will take up.

If the datatype is an integer - let's get it's length

Definition at line 282 of file VariadicTable.h.

284  {
285  if (data == 0)
286  return 1;
287 
288  return std::log10(data) + 1;
289  }

◆ sizeOfData() [3/3]

template<class... Ts>
size_t VariadicTable< Ts >::sizeOfData (   ...)
inlineprotected

If it doesn't...

let's just use a statically set size

Definition at line 294 of file VariadicTable.h.

294 { return _static_column_size; }
unsigned int _static_column_size
Size of columns that we can&#39;t get the size of.

Member Data Documentation

◆ _cell_padding

template<class... Ts>
unsigned int VariadicTable< Ts >::_cell_padding
protected

Size of the cell padding.

Definition at line 377 of file VariadicTable.h.

Referenced by VariadicTable< Ts >::print(), and VariadicTable< Ts >::print_each().

◆ _column_format

template<class... Ts>
std::vector<VariadicTableColumnFormat> VariadicTable< Ts >::_column_format
protected

◆ _column_sizes

template<class... Ts>
std::vector<unsigned int> VariadicTable< Ts >::_column_sizes
protected

Holds the printable width of each column.

Definition at line 383 of file VariadicTable.h.

Referenced by VariadicTable< Ts >::print(), VariadicTable< Ts >::print_each(), and VariadicTable< Ts >::size_columns().

◆ _data

template<class... Ts>
std::vector<DataTuple> VariadicTable< Ts >::_data
protected

◆ _headers

template<class... Ts>
std::vector<std::string> VariadicTable< Ts >::_headers
protected

The column headers.

Definition at line 368 of file VariadicTable.h.

Referenced by VariadicTable< Ts >::print(), and VariadicTable< Ts >::size_columns().

◆ _num_columns

template<class... Ts>
unsigned int VariadicTable< Ts >::_num_columns
protected

Number of columns in the table.

Definition at line 371 of file VariadicTable.h.

Referenced by VariadicTable< Ts >::print(), VariadicTable< Ts >::size_columns(), and VariadicTable< Ts >::VariadicTable().

◆ _precision

template<class... Ts>
std::vector<int> VariadicTable< Ts >::_precision
protected

Precision For each column.

Definition at line 389 of file VariadicTable.h.

Referenced by VariadicTable< Ts >::print_each(), and VariadicTable< Ts >::setColumnPrecision().

◆ _static_column_size

template<class... Ts>
unsigned int VariadicTable< Ts >::_static_column_size
protected

Size of columns that we can't get the size of.

Definition at line 374 of file VariadicTable.h.

Referenced by VariadicTable< Ts >::sizeOfData().

◆ left_type

template<class... Ts>
decltype(&std::left) typedef VariadicTable< Ts >::left_type
protected

Definition at line 164 of file VariadicTable.h.

◆ right_type

template<class... Ts>
decltype(&std::right) typedef VariadicTable< Ts >::right_type
protected

Definition at line 163 of file VariadicTable.h.


The documentation for this class was generated from the following files: