https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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 <VariadicTable.h>

Public Types

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

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.
 
void addRow (Ts... entries)
 Add a row of data.
 
template<typename StreamType >
void print (StreamType &stream)
 Pretty print the table of data.
 
void setColumnFormat (const std::vector< VariadicTableColumnFormat > &column_format)
 Set how to format numbers for each column.
 
void setColumnPrecision (const std::vector< int > &precision)
 Set how many digits of precision to show for floating point numbers.
 

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.
 
template<typename TupleType , typename StreamType >
void print_each (TupleType &&t, StreamType &stream)
 This is what gets called first.
 
template<class T >
size_t sizeOfData (const T &data, decltype(((T *) nullptr) ->size()) *=nullptr)
 Try to find the size the column will take up.
 
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.
 
size_t sizeOfData (...)
 If it doesn't... let's just use a statically set size.
 
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.
 
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.
 
template<typename TupleType >
void size_each (TupleType &&t, std::vector< unsigned int > &sizes)
 The function that is actually called that starts the recursion.
 
void size_columns ()
 Finds the size each column should be and set it in _column_sizes.
 

Static Protected Member Functions

template<typename T >
static auto justify (int)
 

Protected Attributes

std::vector< std::string > _headers
 The column headers.
 
unsigned int _num_columns
 Number of columns in the table.
 
unsigned int _static_column_size
 Size of columns that we can't get the size of.
 
unsigned int _cell_padding
 Size of the cell padding.
 
std::vector< DataTuple_data
 The actual data.
 
std::vector< unsigned int_column_sizes
 Holds the printable width of each column.
 
std::vector< VariadicTableColumnFormat_column_format
 Column Format.
 
std::vector< int_precision
 Precision For each column.
 

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 61 of file VariadicTable.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 }
std::vector< std::string > _headers
The column headers.
unsigned int _static_column_size
Size of columns that we can't get the size of.
unsigned int _cell_padding
Size of the cell padding.
unsigned int _num_columns
Number of columns in the table.

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.

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

Referenced by ReporterData::restoreState().

◆ 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.

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 }
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.
void size_columns()
Finds the size each column should be and set it in _column_sizes.
std::vector< unsigned int > _column_sizes
Holds the printable width of each column.

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

◆ print_each() [1/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 }

◆ print_each() [2/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.

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.
std::vector< VariadicTableColumnFormat > _column_format
Column Format.

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

◆ 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

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

Definition at line 149 of file VariadicTable.h.

150 {
151 assert(column_format.size() == std::tuple_size<DataTuple>::value);
152
153 _column_format = column_format;
154 }

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

◆ 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

@column_format 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 }

◆ 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.

335 {
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...

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

◆ 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.

298 {
299 }

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

◆ size_each() [2/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 }

◆ size_each() [3/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 }
size_t sizeOfData(const T &data, decltype(((T *) nullptr) ->size()) *=nullptr)
Try to find the size the column will take up.

◆ sizeOfData() [1/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; }

◆ sizeOfData() [2/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.

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

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

◆ sizeOfData() [3/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 }

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: