ITK 6.0.0
Insight Toolkit
 
Loading...
Searching...
No Matches
itkPrintHelper.h
Go to the documentation of this file.
1/*=========================================================================
2 *
3 * Copyright NumFOCUS
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0.txt
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *=========================================================================*/
18
19#ifndef itkPrintHelper_h
20#define itkPrintHelper_h
21
22#include "itkMacro.h"
23#include "itkIndent.h"
24
25#include <array>
26#include <iostream>
27#include <iterator>
28#include <vector>
29#include <list>
30#include <type_traits>
31
32
33namespace itk
34{
35// Forward declaration so itkPrintHelper.h can be safely included from
36// itkMacro.h without re-entering itkNumericTraits.h (which itself uses
37// macros defined later in itkMacro.h). Every PrintNumericTrait() call
38// site needs the full NumericTraits<T> specialization in scope, but those
39// sites already #include "itkNumericTraits.h" directly or transitively.
40template <typename T>
41class NumericTraits;
42} // namespace itk
43
45{
46
47// Forward declarations so the per-container bodies below see all overloads at
48// definition time. Required for nested cases like vector<list<T>>, where the
49// recursive `os << *it` is parsed before the list overload would otherwise be
50// declared, and ADL on std container types never reaches itk::print_helper.
51// PrintNumericTrait further down also dispatches through `os << value` and
52// must see these forward declarations to instantiate against std container
53// member types at the call site.
54template <typename T>
55std::ostream &
56operator<<(std::ostream & os, const std::vector<T> & v);
57
58template <typename T>
59std::ostream &
60operator<<(std::ostream & os, const std::list<T> & l);
61
62template <typename T, size_t VLength>
63std::ostream &
64operator<<(std::ostream & os, const std::array<T, VLength> & container);
65
66template <typename T, size_t VLength, typename = std::enable_if_t<!std::is_same_v<T, char>>>
67std::ostream &
68operator<<(std::ostream & os, const T (&arr)[VLength]);
69
96template <typename T>
97inline void
98PrintNumericTrait(std::ostream & os, const Indent & indent, const char * name, const T & value)
99{
100 os << indent << name << ": ";
101 if constexpr (std::is_same_v<T, typename NumericTraits<T>::PrintType>)
102 {
103 os << value;
104 }
105 else
106 {
107 os << static_cast<typename NumericTraits<T>::PrintType>(value);
108 }
109 os << std::endl;
110}
111
112template <typename T>
113std::ostream &
114operator<<(std::ostream & os, const std::vector<T> & v)
115{
116 if (v.empty())
117 {
118 return os << "[]";
119 }
120
121 os << '[';
122 // Manual loop so that an unqualified `os << *it` resolves overloads in
123 // itk::print_helper for nested containers; std::ostream_iterator inserts
124 // from inside namespace std and would not see them.
125 for (auto it = v.begin(); it != std::prev(v.end()); ++it)
126 {
127 os << *it << ", ";
128 }
129 return os << v.back() << ']';
130}
131
132template <typename T>
133std::ostream &
134operator<<(std::ostream & os, const std::list<T> & l)
135{
136 if (l.empty())
137 {
138 return os << "[]";
139 }
140
141 os << '[';
142 for (auto it = l.begin(); it != std::prev(l.end()); ++it)
143 {
144 os << *it << ", ";
145 }
146 return os << l.back() << ']';
147}
148
149template <typename T, size_t VLength>
150std::ostream &
151operator<<(std::ostream & os, [[maybe_unused]] const std::array<T, VLength> & container)
152{
153 if constexpr (VLength == 0)
154 {
155 return os << "()";
156 }
157 else
158 {
159 os << '(';
160 for (auto it = container.cbegin(); it != std::prev(container.cend()); ++it)
161 {
162 os << *it << ", ";
163 }
164 return os << container.back() << ')';
165 }
166}
167
168// Stream insertion operator for C-style arrays, excluding character arrays (strings)
169template <typename T, size_t VLength, typename>
170std::ostream &
171operator<<(std::ostream & os, const T (&arr)[VLength])
172{
173 if constexpr (VLength == 0)
174 {
175 return os << "()";
176 }
177
178 os << '(';
179 for (size_t i = 0; i < VLength - 1; ++i)
180 {
181 os << arr[i] << ", ";
182 }
183 return os << arr[VLength - 1] << ')';
184}
185
186} // namespace itk::print_helper
187
188#endif // itkPrintHelper_h
Control indentation during Print() invocation.
Definition itkIndent.h:51
Define additional traits for native types such as int or float.
void PrintNumericTrait(std::ostream &os, const Indent &indent, const char *name, const T &value)
Print "<name>: <value>\n" indented, matching ITK's PrintSelf style.
std::ostream & operator<<(std::ostream &os, const std::vector< T > &v)
The "itk" namespace contains all Insight Segmentation and Registration Toolkit (ITK) classes....