https://mooseframework.inl.gov
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<std::size_t I, typename TupleType , typename StreamType >
void print_each (TupleType &&t, StreamType &stream, std::integral_constant< size_t, I >)
 These three functions print out each item in a Tuple into the table. More...
 
template<typename TupleType , typename StreamType >
void print_each (TupleType &&t, StreamType &stream)
 This 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 >
static auto justify (int)
 

Protected Attributes

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 34 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 65 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 73 of file VariadicTable.h.

76  : _headers(headers),
77  _num_columns(std::tuple_size<DataTuple>::value),
78  _static_column_size(static_column_size),
79  _cell_padding(cell_padding)
80  {
81  assert(headers.size() == _num_columns);
82  }
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 92 of file VariadicTable.h.

Referenced by ReporterData::restoreState().

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

◆ justify()

template<class... Ts>
template<typename T >
static auto VariadicTable< Ts >::justify ( int  )
inlinestaticprotected

Definition at line 172 of file VariadicTable.h.

173  {
174  if constexpr (std::is_arithmetic<typename std::remove_reference<T>::type>::value)
175  // If it's a floating point value
176  return std::right;
177  else
178  // Otherwise
179  return std::left;
180  }

◆ print()

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

Pretty print the table of data.

Definition at line 98 of file VariadicTable.h.

Referenced by PerfGraph::print(), SolutionInvalidity::print(), PerfGraph::printHeaviestBranch(), and SolutionInvalidity::printHistory().

99  {
100  size_columns();
101 
102  // Start computing the total width
103  // First - we will have _num_columns + 1 "|" characters
104  unsigned int total_width = _num_columns + 1;
105 
106  // Now add in the size of each colum
107  for (auto & col_size : _column_sizes)
108  total_width += col_size + (2 * _cell_padding);
109 
110  // Print out the top line
111  stream << std::string(total_width, '-') << "\n";
112 
113  // Print out the headers
114  stream << "|";
115  for (unsigned int i = 0; i < _num_columns; i++)
116  {
117  // Must find the center of the column
118  auto half = _column_sizes[i] / 2;
119  half -= _headers[i].size() / 2;
120 
121  stream << std::string(_cell_padding, ' ') << std::setw(_column_sizes[i]) << std::left
122  << std::string(half, ' ') + _headers[i] << std::string(_cell_padding, ' ') << "|";
123  }
124 
125  stream << "\n";
126 
127  // Print out the line below the header
128  stream << std::string(total_width, '-') << "\n";
129 
130  // Now print the rows of the table
131  for (auto & row : _data)
132  {
133  stream << "|";
134  print_each(row, stream);
135  stream << "\n";
136  }
137 
138  // Print out the line below the header
139  stream << std::string(total_width, '-') << std::endl;
140  }
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.
std::vector< unsigned int > _column_sizes
Holds the printable width of each column.
void print_each(TupleType &&t, StreamType &stream, std::integral_constant< size_t, I >)
These three functions print out each item in a Tuple into the table.
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/2]

template<class... Ts>
template<std::size_t I, typename TupleType , typename StreamType >
void VariadicTable< Ts >::print_each ( TupleType &&  t,
StreamType &  stream,
std::integral_constant< size_t, I >   
)
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 gets called on each item

Definition at line 196 of file VariadicTable.h.

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

197  {
198  auto & val = std::get<I>(t);
199 
200  auto original_precision = stream.precision();
201  auto original_flags = stream.flags();
202 
203  // Set the precision
204  if (!_precision.empty())
205  {
206  assert(_precision.size() ==
207  std::tuple_size<typename std::remove_reference<TupleType>::type>::value);
208 
209  stream << std::setprecision(_precision[I]);
210  }
211 
212  // Set the format
213  if (!_column_format.empty())
214  {
215  assert(_column_format.size() ==
216  std::tuple_size<typename std::remove_reference<TupleType>::type>::value);
217 
219  stream << std::scientific;
220 
222  stream << std::fixed;
223 
225  stream << std::fixed << std::setprecision(2);
226  }
227 
228  stream << std::string(_cell_padding, ' ') << std::setw(_column_sizes[I])
229  << justify<decltype(val)>(0) << val << std::string(_cell_padding, ' ') << "|";
230 
231  // Restore the format
232  if (!_column_format.empty())
233  stream.flags(original_flags);
234 
235  // Restore the precision
236  if (!_precision.empty())
237  stream.precision(original_precision);
238 
239  // Recursive call to print the next item (if there are any left)
240  if constexpr (I + 1 != std::tuple_size<typename std::remove_reference<TupleType>::type>::value)
241  print_each(std::forward<TupleType>(t), stream, std::integral_constant<size_t, I + 1>());
242  }
std::vector< int > _precision
Precision For each column.
unsigned int _cell_padding
Size of the cell padding.
std::vector< VariadicTableColumnFormat > _column_format
Column Format.
std::vector< unsigned int > _column_sizes
Holds the printable width of each column.
void print_each(TupleType &&t, StreamType &stream, std::integral_constant< size_t, I >)
These three functions print out each item in a Tuple into the table.

◆ print_each() [2/2]

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

This is what gets called first.

Definition at line 248 of file VariadicTable.h.

249  {
250  print_each(std::forward<TupleType>(t), stream, std::integral_constant<size_t, 0>());
251  }
void print_each(TupleType &&t, StreamType &stream, std::integral_constant< size_t, I >)
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 149 of file VariadicTable.h.

Referenced by PerfGraph::printHeaviestSections(), SolutionInvalidity::summaryTable(), SolutionInvalidity::transientTable(), and PerfGraph::treeTable().

150  {
151  assert(column_format.size() == std::tuple_size<DataTuple>::value);
152 
153  _column_format = column_format;
154  }
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 163 of file VariadicTable.h.

164  {
165  assert(precision.size() == std::tuple_size<DataTuple>::value);
166  _precision = precision;
167  }
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 334 of file VariadicTable.h.

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

335  {
336  _column_sizes.resize(_num_columns);
337 
338  // Temporary for querying each row
339  std::vector<unsigned int> column_sizes(_num_columns);
340 
341  // Start with the size of the headers
342  for (unsigned int i = 0; i < _num_columns; i++)
343  _column_sizes[i] = _headers[i].size();
344 
345  // Grab the size of each entry of each row and see if it's bigger
346  for (auto & row : _data)
347  {
348  size_each(row, column_sizes);
349 
350  for (unsigned int i = 0; i < _num_columns; i++)
351  _column_sizes[i] = std::max(_column_sizes[i], column_sizes[i]);
352  }
353  }
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.
auto max(const L &left, const R &right)
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 293 of file VariadicTable.h.

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

298  {
299  }

◆ 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 309 of file VariadicTable.h.

310  {
311  sizes[I] = sizeOfData(std::get<I>(t));
312 
313  // Override for Percent
314  if (!_column_format.empty())
316  sizes[I] = 6; // 100.00
317 
318  // Continue the recursion
319  size_each(std::forward<TupleType>(t), sizes, std::integral_constant<size_t, I + 1>());
320  }
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 326 of file VariadicTable.h.

327  {
328  size_each(std::forward<TupleType>(t), sizes, std::integral_constant<size_t, 0>());
329  }
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 259 of file VariadicTable.h.

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

260  {
261  return data.size();
262  }

◆ 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 270 of file VariadicTable.h.

272  {
273  if (data == 0)
274  return 1;
275 
276  return std::log10(data) + 1;
277  }

◆ 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 282 of file VariadicTable.h.

282 { 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 365 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 371 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 356 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 359 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 377 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 362 of file VariadicTable.h.

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


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