Skip to content

Commit e7bce87

Browse files
committed
BUG: Fix printing of values in MetaDataObject
Also removes dead code related to METADATAPRINT Fix #1454
1 parent 7d8b95d commit e7bce87

File tree

5 files changed

+91
-72
lines changed

5 files changed

+91
-72
lines changed

Modules/Core/Common/include/itkMetaDataObject.h

Lines changed: 10 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,6 @@ namespace itk
6363
* string "[UNKNOWN PRINT CHARACTERISTICS]" that works for all possible
6464
* MetaDataObject types.
6565
*
66-
* The application developer may overload the default implementation to provide
67-
* a specialized Print() characteristics to produce results desirable for their application.
68-
* A set of very crude Macros {NATIVE_TYPE_METADATAPRINT, ITK_OBJECT_TYPE_METADATAPRINT_1COMMA,
69-
* ITK_IMAGE_TYPE_METADATAPRINT } are provided to facilitate a very simple implementation, and as an example.
70-
*
7166
* \ingroup ITKCommon
7267
*
7368
*/
@@ -123,13 +118,6 @@ class ITK_TEMPLATE_EXPORT MetaDataObject : public MetaDataObjectBase
123118
void
124119
SetMetaDataObjectValue(const MetaDataObjectType & newValue);
125120

126-
/**
127-
* Defines the default behavior for printing out this element
128-
* \param os An output stream
129-
*/
130-
void
131-
Print(std::ostream & os) const override;
132-
133121
/** Returns (metaDataObject1 == metaDataObject2). */
134122
friend bool
135123
operator==(const Self & lhs, const Self & rhs)
@@ -144,10 +132,19 @@ class ITK_TEMPLATE_EXPORT MetaDataObject : public MetaDataObjectBase
144132
return !(lhs == rhs);
145133
}
146134

135+
/** Helper to print contents of a MetaDataObject. */
136+
void PrintValue(std::ostream & os) const;
137+
147138
protected:
148139
MetaDataObject() = default;
149140
~MetaDataObject() override = default;
150141

142+
/**
143+
* Defines the default behavior for printing out this element
144+
* \param os An output stream
145+
*/
146+
void PrintSelf(std::ostream & os, Indent indent) const override;
147+
151148
private:
152149
/** Assigns the value of `source` to `target`.
153150
* \note The trailing return type is there, just to enable SFINAE.*/
@@ -262,53 +259,8 @@ ExposeMetaData(const MetaDataDictionary & Dictionary, const std::string key, T &
262259
return true;
263260
}
264261

265-
} // end namespace itk
266-
267-
/**
268-
* \def ITK_NATIVE_TYPE_METADATAPRINT( TYPE_NAME )
269-
* \brief An ugly macro to facilitate creating a simple implementation of
270-
* the MetaDataObject<Type>::Print() function for types that
271-
* have operator<< defined.
272-
* \param TYPE_NAME the native type parameter type
273-
*/
274-
#define ITK_NATIVE_TYPE_METADATAPRINT(TYPE_NAME) \
275-
template <> \
276-
void itk::MetaDataObject<TYPE_NAME>::Print(std::ostream & os) const \
277-
{ \
278-
os << this->m_MetaDataObjectValue << std::endl; \
279-
}
280-
281-
/**
282-
* \def ITK_OBJECT_TYPE_METADATAPRINT_1COMMA( TYPE_NAME_PART1, TYPE_NAME_PART2 )
283-
* \brief An ugly macro to facilitate creating a simple implementation of
284-
* the MetaDataObject< Type >::Print() function for
285-
* itk::Objects that have 1 comma in their type definition
286-
* \param TYPE_NAME_PART1
287-
* \param TYPE_NAME_PART2
288-
*/
289-
#define ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(TYPE_NAME_PART1, TYPE_NAME_PART2) \
290-
template <> \
291-
void itk::MetaDataObject<TYPE_NAME_PART1, TYPE_NAME_PART2>::Print(std::ostream & os) const \
292-
{ \
293-
this->m_MetaDataObjectValue->Print(os); \
294-
}
295262

296-
/**
297-
* \def ITK_IMAGE_TYPE_METADATAPRINT( STORAGE_TYPE )
298-
* An ugly macro to facilitate creating a simple implementation of
299-
* the MetaDataObject<Type>::Print() function for
300-
* itk::Image\<STORAGE_TYPE,[1-8]\>\::Pointer
301-
* \param STORAGE_TYPE The storage type of the image type to print.
302-
*/
303-
#define ITK_IMAGE_TYPE_METADATAPRINT(STORAGE_TYPE) \
304-
ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image<STORAGE_TYPE, 1>::Pointer) \
305-
ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image<STORAGE_TYPE, 2>::Pointer) \
306-
ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image<STORAGE_TYPE, 3>::Pointer) \
307-
ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image<STORAGE_TYPE, 4>::Pointer) \
308-
ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image<STORAGE_TYPE, 5>::Pointer) \
309-
ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image<STORAGE_TYPE, 6>::Pointer) \
310-
ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image<STORAGE_TYPE, 7>::Pointer) \
311-
ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image<STORAGE_TYPE, 8>::Pointer)
263+
} // end namespace itk
312264

313265
#ifndef ITK_MANUAL_INSTANTIATION
314266
# include "itkMetaDataObject.hxx"

Modules/Core/Common/include/itkMetaDataObject.hxx

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,70 @@
2828
#ifndef itkMetaDataObject_hxx
2929
#define itkMetaDataObject_hxx
3030

31+
#include <type_traits>
32+
#include <iterator>
33+
34+
template <typename T, typename = void>
35+
inline constexpr bool is_iterable_print_v = false;
36+
37+
// Specialize for std::vector<T>
38+
template <typename T>
39+
inline constexpr bool is_iterable_print_v<std::vector<T>, std::void_t<>> = true;
40+
41+
// Specialize for std::vector<std::vector<T>>
42+
template <typename T>
43+
inline constexpr bool is_iterable_print_v<std::vector<std::vector<T>>, std::void_t<>> = true;
3144

3245
namespace itk
3346
{
47+
template <typename TIterable>
48+
void printIterable(std::ostream &os, const TIterable& iterable)
49+
{
50+
if constexpr (is_iterable_print_v<TIterable>) {
51+
os << "[";
52+
auto begin = std::begin(iterable);
53+
auto end = std::end(iterable);
54+
for (auto it = begin; it != end; ++it) {
55+
if (it != begin) {
56+
os << ", "; // Separator for elements
57+
}
58+
printIterable(os, *it); // No additional indent for nested iterables
59+
}
60+
os << "]"; // Closing bracket
61+
} else {
62+
os << iterable; // Handle non-iterable types
63+
}
64+
}
65+
66+
template <typename MetaDataObjectType>
67+
void
68+
MetaDataObject<MetaDataObjectType>::PrintValue(std::ostream & os) const
69+
{
70+
if constexpr (is_iterable_print_v<MetaDataObjectType>) {
71+
os << "[";
72+
auto begin = std::begin(m_MetaDataObjectValue);
73+
auto end = std::end(m_MetaDataObjectValue);
74+
for (auto it = begin; it != end; ++it) {
75+
if (it != begin) {
76+
os << ", ";
77+
}
78+
printIterable(os, *it);
79+
}
80+
os << "]";
81+
} else {
82+
os << m_MetaDataObjectValue;
83+
}
84+
}
85+
86+
template <typename MetaDataObjectType>
87+
void
88+
MetaDataObject<MetaDataObjectType>::PrintSelf(std::ostream & os, Indent indent) const
89+
{
90+
os << indent;
91+
this->PrintValue(os);
92+
os << std::endl;
93+
}
94+
3495
template <typename MetaDataObjectType>
3596
const char *
3697
MetaDataObject<MetaDataObjectType>::GetMetaDataObjectTypeName() const
@@ -59,12 +120,6 @@ MetaDataObject<MetaDataObjectType>::SetMetaDataObjectValue(const MetaDataObjectT
59120
Self::Assign(m_MetaDataObjectValue, newValue);
60121
}
61122

62-
template <typename MetaDataObjectType>
63-
void
64-
MetaDataObject<MetaDataObjectType>::Print(std::ostream & os) const
65-
{
66-
Superclass::Print(os);
67-
}
68123

69124
} // end namespace itk
70125

Modules/Core/Common/include/itkMetaDataObjectBase.h

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,17 +86,16 @@ class ITKCommon_EXPORT MetaDataObjectBase : public LightObject
8686
return !(lhs == rhs);
8787
}
8888

89+
protected:
90+
MetaDataObjectBase();
91+
~MetaDataObjectBase() override;
8992

9093
/**
9194
* Defines the default behavior for printing out this element
9295
* \param os An output stream
9396
*/
94-
virtual void
95-
Print(std::ostream & os) const;
96-
97-
protected:
98-
MetaDataObjectBase();
99-
~MetaDataObjectBase() override;
97+
void
98+
PrintSelf(std::ostream & os, Indent indent) const override;
10099

101100
private:
102101
virtual bool

Modules/Core/Common/src/itkMetaDataObjectBase.cxx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ MetaDataObjectBase::GetMetaDataObjectTypeInfo() const
4141

4242

4343
void
44-
MetaDataObjectBase::Print(std::ostream & os) const
44+
MetaDataObjectBase::PrintSelf(std::ostream & os, Indent indent) const
4545
{
46-
os << "[UNKNOWN_PRINT_CHARACTERISTICS]" << std::endl;
46+
os << indent << "[UNKNOWN_PRINT_CHARACTERISTICS]" << std::endl;
4747
}
4848

4949
} // end namespace itk

Modules/Core/Common/test/itkMetaDataObjectTest.cxx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ testMetaData(const TMetaData & value)
4444
std::cout << "The metadata's type name is: " << metaDataObject->GetMetaDataObjectTypeName() << std::endl;
4545
std::cout << "The metadata object: " << std::endl;
4646
metaDataObject->Print(std::cout);
47+
std::cout << "The metadata value only: " << std::endl;
48+
metaDataObject->PrintValue(std::cout);
4749

4850
std::cout << std::endl << std::endl;
4951

@@ -67,7 +69,18 @@ itkMetaDataObjectTest(int, char *[])
6769
result += testMetaData<long long>(-24);
6870
result += testMetaData<float>(-24);
6971
result += testMetaData<double>(-24);
72+
// Exercise printing of iterable types
73+
// std::string is specialized to be treated as non-iterable
7074
result += testMetaData<std::string>("I T K");
75+
auto v3 = std::vector<double>{ 1.0, 2.0, 3.0 };
76+
result += testMetaData<std::vector<double>>(v3);
77+
result += testMetaData<std::vector<std::vector<double>>>(std::vector<std::vector<double>>{ v3, v3 });
78+
// Exercise itk::Array
79+
auto a3 = itk::Array<double>(3, 5.0);
80+
result += testMetaData<itk::Array<double>>(a3);
81+
// Exercise itk::Matrix
82+
auto m3 = itk::Matrix<double, 3, 3>();
83+
result += testMetaData<itk::Matrix<double, 3, 3>>(m3);
7184

7285
using ImageType = itk::Image<unsigned short, 3>;
7386
ImageType::Pointer image = nullptr;

0 commit comments

Comments
 (0)