Version: SMASH-3.3
smash::detail Namespace Reference

specialize a type for all of the STL containers. More...

Classes

struct  KeyTraits
 Class template to store Key traits outside the Key class, allowing for reuse both in the Key class itself and in helper implementation details. More...
 
struct  is_stl_container
 Implementation of the type trait to infer if a type is an STL container. More...
 
struct  is_stl_container< std::vector< Args... > >
 Trait specialization for std::vector. More...
 
struct  is_stl_container< std::set< Args... > >
 Trait specialization for std::set. More...
 
struct  is_stl_container< std::map< Args... > >
 Trait specialization for std::map. More...
 

Functions

template<typename T >
const KeyTraits< T >::validator_type & get_default_validator () noexcept
 Function template to get a default trivial validator. More...
 
template<typename T >
constexpr auto type_name ()
 Get type of variable as string in a human-readable way. More...
 
template<typename N , typename = std::enable_if_t<std::is_floating_point_v<N>>>
bool almost_equal_knuthish (const N x, const N y, const N epsilon, const N threshold=N{0.0}) noexcept
 Compare whether two floating-point numbers are approximately equal à la Knuth up to a given tolerance. More...
 

Detailed Description

specialize a type for all of the STL containers.

Function Documentation

◆ get_default_validator()

template<typename T >
const KeyTraits<T>::validator_type& smash::detail::get_default_validator ( )
noexcept

Function template to get a default trivial validator.

Returns
A const reference to a functor that always returns true .
Attention
It might look unnecessary to have a function returning the functor and you might think that the functor as a constant global variable template would be enough. However, this would be in general wrong because this functor is used in the Key constructors which are used by the InputKeys class, that is a collection of static Keys. Hence, since initialization order of static/global objects in C++ is undefined, we need to to do something else. We use therefore the "construct on first use idiom", making the functor a static object in a function scope. For more information, refer for example to ISO C++ FAQ.

Definition at line 135 of file key.h.

135  {
136  static const typename KeyTraits<T>::validator_type always_true =
137  [](const T&) noexcept { return true; };
138  return always_true;
139 }

◆ type_name()

template<typename T >
constexpr auto smash::detail::type_name ( )
constexpr

Get type of variable as string in a human-readable way.

Template Parameters
TThe type to be returned.
Returns
A std::string containing the name of the type.

Definition at line 27 of file numeric_cast.h.

27  {
28  std::string_view name, prefix, suffix;
29 #ifdef __clang__
30  name = __PRETTY_FUNCTION__;
31  prefix = "auto smash::detail::type_name() [T = ";
32  suffix = "]";
33 #elif defined(__GNUC__)
34  name = __PRETTY_FUNCTION__;
35  prefix = "constexpr auto smash::detail::type_name() [with T = ";
36  suffix = "]";
37 #elif defined(_MSC_VER)
38  name = __FUNCSIG__;
39  prefix = "auto __cdecl smash::detail::type_name<";
40  suffix = ">(void)";
41 #else
42  name = "UNKNOWN";
43  prefix = "";
44  suffix = "";
45 #endif
46  name.remove_prefix(prefix.size());
47  name.remove_suffix(suffix.size());
48  return std::string{name};
49 }

◆ almost_equal_knuthish()

template<typename N , typename = std::enable_if_t<std::is_floating_point_v<N>>>
bool smash::detail::almost_equal_knuthish ( const N  x,
const N  y,
const N  epsilon,
const N  threshold = N{0.0} 
)
noexcept

Compare whether two floating-point numbers are approximately equal à la Knuth up to a given tolerance.

On top of Knuth's tolerance predicate some corner cases are treated and the caller can specify a threshold as last parameter to make the test consider numbers equal if the absolute value of their difference is below of it.

Parameters
[in]xFirst of the two numbers.
[in]ySecond of the two numbers.
[in]epsilonThe relative tolerance for the test.
[in]thresholdThreshold for the number comparison. By default this is zero, implying no threshold is considered.
Returns
false if either x or y is not a finite number, provided that the type supports non-numeric representations (i.e. is infinite or NAN);
true if x == y;
true if x == 0 and if \( |x| \le \varepsilon\);
true if y == 0 and if \( |y| \le \varepsilon\);
true if \( |x - y| \le M_\mathrm{threshold} \);
true if \( |x - y| \le \varepsilon \cdot \max(|x|, |y|) \) (Knuth's tolerance predicate);
false otherwise.

Definition at line 59 of file numerics.h.

60  {0.0}) noexcept {
61  assert(epsilon > 0);
62  assert(threshold >= 0);
63  if constexpr (std::numeric_limits<N>::is_iec559) {
64  if (!std::isfinite(x) || !std::isfinite(y)) {
65  return false;
66  }
67  }
68  if (x == y)
69  return true;
70  else if (x == 0)
71  return std::abs(y) <= epsilon;
72  else if (y == 0)
73  return std::abs(x) <= epsilon;
74  else
75  return std::abs(x - y) <= threshold ||
76  std::abs(x - y) <= epsilon * std::max(std::abs(x), std::abs(y));
77 }