diff --git a/Modules/Core/Common/include/itkMetaDataObject.h b/Modules/Core/Common/include/itkMetaDataObject.h index bbf2f7bd8cf..3b2c80117e2 100644 --- a/Modules/Core/Common/include/itkMetaDataObject.h +++ b/Modules/Core/Common/include/itkMetaDataObject.h @@ -58,15 +58,8 @@ namespace itk * and redefining the copy constructor and initializing constructor and the Get/Set functions * to work around those deficiencies. * - * The behavior of the MetaDataObject::Print() function has many plausible - * application dependent implementations. The default implementation prints the - * string "[UNKNOWN PRINT CHARACTERISTICS]" that works for all possible - * MetaDataObject types. - * - * The application developer may overload the default implementation to provide - * a specialized Print() characteristics to produce results desirable for their application. - * A set of very crude Macros {NATIVE_TYPE_METADATAPRINT, ITK_OBJECT_TYPE_METADATAPRINT_1COMMA, - * ITK_IMAGE_TYPE_METADATAPRINT } are provided to facilitate a very simple implementation, and as an example. + * The default implementation prints uses the MetaDataObjectType's Print or operator<< if available. Otherwise, it + * prints string "[UNKNOWN PRINT CHARACTERISTICS]". * * \ingroup ITKCommon * @@ -264,52 +257,6 @@ ExposeMetaData(const MetaDataDictionary & Dictionary, const std::string key, T & } // end namespace itk -/** - * \def ITK_NATIVE_TYPE_METADATAPRINT( TYPE_NAME ) - * \brief An ugly macro to facilitate creating a simple implementation of - * the MetaDataObject::Print() function for types that - * have operator<< defined. - * \param TYPE_NAME the native type parameter type - */ -#define ITK_NATIVE_TYPE_METADATAPRINT(TYPE_NAME) \ - template <> \ - void itk::MetaDataObject::Print(std::ostream & os) const \ - { \ - os << this->m_MetaDataObjectValue << std::endl; \ - } - -/** - * \def ITK_OBJECT_TYPE_METADATAPRINT_1COMMA( TYPE_NAME_PART1, TYPE_NAME_PART2 ) - * \brief An ugly macro to facilitate creating a simple implementation of - * the MetaDataObject< Type >::Print() function for - * itk::Objects that have 1 comma in their type definition - * \param TYPE_NAME_PART1 - * \param TYPE_NAME_PART2 - */ -#define ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(TYPE_NAME_PART1, TYPE_NAME_PART2) \ - template <> \ - void itk::MetaDataObject::Print(std::ostream & os) const \ - { \ - this->m_MetaDataObjectValue->Print(os); \ - } - -/** - * \def ITK_IMAGE_TYPE_METADATAPRINT( STORAGE_TYPE ) - * An ugly macro to facilitate creating a simple implementation of - * the MetaDataObject::Print() function for - * itk::Image\\::Pointer - * \param STORAGE_TYPE The storage type of the image type to print. - */ -#define ITK_IMAGE_TYPE_METADATAPRINT(STORAGE_TYPE) \ - ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image::Pointer) \ - ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image::Pointer) \ - ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image::Pointer) \ - ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image::Pointer) \ - ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image::Pointer) \ - ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image::Pointer) \ - ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image::Pointer) \ - ITK_OBJECT_TYPE_METADATAPRINT_1COMMA(itk::Image::Pointer) - #ifndef ITK_MANUAL_INSTANTIATION # include "itkMetaDataObject.hxx" #endif diff --git a/Modules/Core/Common/include/itkMetaDataObject.hxx b/Modules/Core/Common/include/itkMetaDataObject.hxx index 23b92f234db..47c2d548956 100644 --- a/Modules/Core/Common/include/itkMetaDataObject.hxx +++ b/Modules/Core/Common/include/itkMetaDataObject.hxx @@ -59,11 +59,45 @@ MetaDataObject::SetMetaDataObjectValue(const MetaDataObjectT Self::Assign(m_MetaDataObjectValue, newValue); } +namespace +{ +template +struct has_Print : std::false_type +{}; + +template +struct has_Print().Print(std::declval()))>> : std::true_type +{}; + +template +struct has_output_operator : std::false_type +{}; + +template +struct has_output_operator() << std::declval())>> + : std::true_type +{}; +} // namespace + template void MetaDataObject::Print(std::ostream & os) const { - Superclass::Print(os); + // future c++20 feature + // constexpr bool hasPrint = false; requires( const &MetaDataObjectType obj ) { obj.Print(os); }; + + if constexpr (has_Print::value) + { + m_MetaDataObjectValue.Print(os); + } + else if constexpr (has_output_operator::value) + { + os << m_MetaDataObjectValue; + } + else + { + Superclass::Print(os); + } } } // end namespace itk diff --git a/Modules/Core/Common/test/itkMetaDataObjectTest.cxx b/Modules/Core/Common/test/itkMetaDataObjectTest.cxx index 84e75b03c2b..35527a3dfb4 100644 --- a/Modules/Core/Common/test/itkMetaDataObjectTest.cxx +++ b/Modules/Core/Common/test/itkMetaDataObjectTest.cxx @@ -68,7 +68,12 @@ itkMetaDataObjectTest(int, char *[]) result += testMetaData(-24); result += testMetaData(-24); result += testMetaData("I T K"); - + result += testMetaData>({ 1.0, 2.0, 3.0 }); + result += testMetaData>>({ { 1.0, 2.0, 3.0 }, { 4.0, 5.0, 6.0 } }); + result += testMetaData(itk::Array(3, 'I')); + result += testMetaData>(itk::Array(3, 3.0)); + result += testMetaData(itk::Matrix()); + result += testMetaData>(itk::Matrix::GetIdentity()); using ImageType = itk::Image; ImageType::Pointer image = nullptr; result += testMetaData(image);