Skip to content

Commit 1afdbce

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

File tree

5 files changed

+102
-72
lines changed

5 files changed

+102
-72
lines changed

Modules/Core/Common/include/itkMetaDataObject.h

Lines changed: 12 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,21 @@ class ITK_TEMPLATE_EXPORT MetaDataObject : public MetaDataObjectBase
144132
return !(lhs == rhs);
145133
}
146134

135+
/** Helper to print contents of a MetaDataObject. */
136+
void
137+
PrintValue(std::ostream & os) const;
138+
147139
protected:
148140
MetaDataObject() = default;
149141
~MetaDataObject() override = default;
150142

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

265-
} // end namespace itk
266264

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-
}
295-
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)
265+
} // end namespace itk
312266

313267
#ifndef ITK_MANUAL_INSTANTIATION
314268
# include "itkMetaDataObject.hxx"

Modules/Core/Common/include/itkMetaDataObject.hxx

Lines changed: 70 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,79 @@
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+
// Specialize for std::vector<T> and std::vector<std::vector<T>>
37+
template <typename T>
38+
inline constexpr bool is_iterable_print_v<std::vector<T>, std::void_t<>> = true;
39+
template <typename T>
40+
inline constexpr bool is_iterable_print_v<std::vector<std::vector<T>>, std::void_t<>> = true;
3141

3242
namespace itk
3343
{
44+
template <typename TIterable>
45+
void
46+
printIterable(std::ostream & os, const TIterable & iterable)
47+
{
48+
if constexpr (is_iterable_print_v<TIterable>)
49+
{
50+
os << "[";
51+
auto begin = std::begin(iterable);
52+
auto end = std::end(iterable);
53+
for (auto it = begin; it != end; ++it)
54+
{
55+
if (it != begin)
56+
{
57+
os << ", ";
58+
}
59+
printIterable(os, *it);
60+
}
61+
os << "]";
62+
}
63+
else
64+
{
65+
// Handle non-iterable types
66+
os << iterable;
67+
}
68+
}
69+
70+
template <typename MetaDataObjectType>
71+
void
72+
MetaDataObject<MetaDataObjectType>::PrintValue(std::ostream & os) const
73+
{
74+
if constexpr (is_iterable_print_v<MetaDataObjectType>)
75+
{
76+
os << "[";
77+
auto begin = std::begin(m_MetaDataObjectValue);
78+
auto end = std::end(m_MetaDataObjectValue);
79+
for (auto it = begin; it != end; ++it)
80+
{
81+
if (it != begin)
82+
{
83+
os << ", ";
84+
}
85+
printIterable(os, *it);
86+
}
87+
os << "]";
88+
}
89+
else
90+
{
91+
os << m_MetaDataObjectValue;
92+
}
93+
}
94+
95+
template <typename MetaDataObjectType>
96+
void
97+
MetaDataObject<MetaDataObjectType>::PrintSelf(std::ostream & os, Indent indent) const
98+
{
99+
os << indent;
100+
this->PrintValue(os);
101+
os << std::endl;
102+
}
103+
34104
template <typename MetaDataObjectType>
35105
const char *
36106
MetaDataObject<MetaDataObjectType>::GetMetaDataObjectTypeName() const
@@ -59,12 +129,6 @@ MetaDataObject<MetaDataObjectType>::SetMetaDataObjectValue(const MetaDataObjectT
59129
Self::Assign(m_MetaDataObjectValue, newValue);
60130
}
61131

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

69133
} // end namespace itk
70134

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

@@ -68,6 +70,17 @@ itkMetaDataObjectTest(int, char *[])
6870
result += testMetaData<float>(-24);
6971
result += testMetaData<double>(-24);
7072
result += testMetaData<std::string>("I T K");
73+
// Exercise printing of std::vector<T> and std::vector<std::vector<T>>
74+
// These two types are special cased in itk::MetaDataObject::PrintValue()
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)