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 <SolutionInvalidity.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 31 of file SolutionInvalidity.h.

Member Typedef Documentation

◆ DataTuple

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

The type stored for each row.

Definition at line 64 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 72 of file VariadicTable.h.

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

91 { _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 171 of file VariadicTable.h.

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

◆ print()

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

Pretty print the table of data.

Definition at line 97 of file VariadicTable.h.

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

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

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

196  {
197  auto & val = std::get<I>(t);
198 
199  auto original_precision = stream.precision();
200  auto original_flags = stream.flags();
201 
202  // Set the precision
203  if (!_precision.empty())
204  {
205  assert(_precision.size() ==
206  std::tuple_size<typename std::remove_reference<TupleType>::type>::value);
207 
208  stream << std::setprecision(_precision[I]);
209  }
210 
211  // Set the format
212  if (!_column_format.empty())
213  {
214  assert(_column_format.size() ==
215  std::tuple_size<typename std::remove_reference<TupleType>::type>::value);
216 
218  stream << std::scientific;
219 
221  stream << std::fixed;
222 
224  stream << std::fixed << std::setprecision(2);
225  }
226 
227  stream << std::string(_cell_padding, ' ') << std::setw(_column_sizes[I])
228  << justify<decltype(val)>(0) << val << std::string(_cell_padding, ' ') << "|";
229 
230  // Restore the format
231  if (!_column_format.empty())
232  stream.flags(original_flags);
233 
234  // Restore the precision
235  if (!_precision.empty())
236  stream.precision(original_precision);
237 
238  // Recursive call to print the next item (if there are any left)
239  if constexpr (I + 1 != std::tuple_size<typename std::remove_reference<TupleType>::type>::value)
240  print_each(std::forward<TupleType>(t), stream, std::integral_constant<size_t, I + 1>());
241  }
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 247 of file VariadicTable.h.

248  {
249  print_each(std::forward<TupleType>(t), stream, std::integral_constant<size_t, 0>());
250  }
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 148 of file VariadicTable.h.

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

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

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

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

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

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

297  {
298  }

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

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

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

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

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

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

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

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

281 { 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 364 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 370 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 355 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 358 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 376 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 361 of file VariadicTable.h.

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


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