hexfloat.h
Go to the documentation of this file.
1 /**
2  * @file hexfloat.h
3  * @brief Helper to support output of real numbers in base 16
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date April 29, 2016
6  *
7  * @note This is going to be obsolete and deprecated as soon as GCC supports
8  * `std::hexfloat` from C++ standard (gcc 5.1).
9  *
10  * @note The manipulator `lar::hexfloat` is *not* equivalent to `std::hexfloat`
11  * in that the former takes one argument and formats only that argument,
12  * while the second takes no argument and all the following floats are formatted
13  * in base 16.
14  */
15 
16 #ifndef LARDATA_RECOBASEART_DUMPERS_HEXFLOAT_H
17 #define LARDATA_RECOBASEART_DUMPERS_HEXFLOAT_H 1
18 
19 // C/C++ standard libraries
20 #include <utility> // std::forward()
21 #include <type_traits> // std::is_same<>
22 #include <cstdio> // std::snprintf()
23 #include <iosfwd> // std::ostream
24 
25 
26 namespace lar {
27 
28  namespace details {
29 
30  template <typename T>
32  public:
33  using real_t = T;
34 
35  // sprintf() does not support floats;
36  // it will probably do some bad thing with them
37  static_assert(
38  !std::is_same<std::decay_t<T>, float>::value,
39  "OptionalHexFloatFormatter does not support float values"
40  );
41 
42  OptionalHexFloatFormatter(real_t v, bool start_active = true)
43  : active(start_active), value(v) {}
44 
45  /// Prints the value set at construction
46  template <typename Stream>
47  Stream& operator() (Stream&& os) const
48  { write(std::forward<Stream>(os), value); return os; }
49 
50 
51  /// Prints the specified value into the specified stream
52  template <typename Stream>
53  void write(Stream&& os, real_t v) const
54  {
55  if (active) write_hexfloat(std::forward<Stream>(os), v);
56  else write_standard(std::forward<Stream>(os), v);
57  }
58 
59  /// Prints the specified value into the specified stream
60  template <typename Stream>
61  static void write_hexfloat(Stream&& os, real_t v)
62  {
63  constexpr auto buf_size = 8 * sizeof(real_t) + 1;
64  char buf[buf_size];
65  std::snprintf(buf, buf_size, "%+24.14a", v);
66  os << buf;
67  }
68 
69  /// Prints the specified value into the specified stream
70  template <typename Stream>
71  static void write_standard(Stream&& os, real_t v) { os << v; }
72 
73  private:
74  bool active; ///< whether we are writing in base 16
75  real_t value; ///< the value to be printed
76 
77  }; // OptionalHexFloatFormatter
78 
79  template <typename T>
80  std::ostream& operator<<
81  (std::ostream& os, details::OptionalHexFloatFormatter<T> fmt)
82  { return fmt(os); }
83 
84  } // namespace details
85 
86 
87  /**
88  * @brief Helper for formatting floats in base 16
89  *
90  * Example of use:
91  *
92  * lar::OptionalHexFloat hexfloat;
93  * constexpr double value = 0.375;
94  *
95  * std::cout << "Hex: " << hexfloat(value) << std::endl;
96  *
97  * hexfloat.disable();
98  *
99  * std::cout << "Dec: " << hexfloat(value) << std::endl;
100  *
101  * The first printout is expected to be in base 16, the second one in base
102  * 10.
103  *
104  */
106 
107  public:
108 
109  /// Constructor: if start_active is true, it will print floats in base 16
110  OptionalHexFloat(bool start_active = true)
111  : active(start_active)
112  {}
113 
114  /// Returns whether base 16 printing is enabled
115  bool enabled() const { return active; }
116 
117  /// Enables base 16 printing (or disables it if enable is false)
118  void enable(bool enable = true) { active = enable; }
119 
120  /// Disables base 16 printing
121  void disable() { active = false; }
122 
123  /// Returns an object that knows what to do with an output stream
124  template <typename T>
125  auto operator() (T value) const { return formatter_t<T>(value, active); }
126 
127  /// Returns an object that knows what to do with an output stream
128  template <typename T>
129  auto operator() (bool this_active, T value) const
130  { return formatter_t<T>(this_active, value); }
131 
132  private:
133  template <typename T>
135 
136  bool active; ///< whether we are writing in base 16
137 
138  }; // OptionalHexFloat
139 
140 
141 } // namespace lar
142 
143 
144 #endif // LARDATA_RECOBASEART_DUMPERS_HEXFLOAT_H
static void write_standard(Stream &&os, real_t v)
Prints the specified value into the specified stream.
Definition: hexfloat.h:71
OptionalHexFloat(bool start_active=true)
Constructor: if start_active is true, it will print floats in base 16.
Definition: hexfloat.h:110
Stream & operator()(Stream &&os) const
Prints the value set at construction.
Definition: hexfloat.h:47
static void write_hexfloat(Stream &&os, real_t v)
Prints the specified value into the specified stream.
Definition: hexfloat.h:61
void write(Stream &&os, real_t v) const
Prints the specified value into the specified stream.
Definition: hexfloat.h:53
real_t value
the value to be printed
Definition: hexfloat.h:75
void disable()
Disables base 16 printing.
Definition: hexfloat.h:121
Helper for formatting floats in base 16.
Definition: hexfloat.h:105
void enable(bool enable=true)
Enables base 16 printing (or disables it if enable is false)
Definition: hexfloat.h:118
bool active
whether we are writing in base 16
Definition: hexfloat.h:136
LArSoft-specific namespace.
OptionalHexFloatFormatter(real_t v, bool start_active=true)
Definition: hexfloat.h:42
bool active
whether we are writing in base 16
Definition: hexfloat.h:74
bool enabled() const
Returns whether base 16 printing is enabled.
Definition: hexfloat.h:115