From 3d8557be0064b437681e7129751ad02273f890cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franz=20P=C3=B6schel?= Date: Fri, 10 Dec 2021 13:16:15 +0100 Subject: [PATCH] Make RecordComponent base class of BaseRecord a template --- include/openPMD/RecordComponent.hpp | 2 +- include/openPMD/backend/Attributable.hpp | 4 +- include/openPMD/backend/BaseRecord.hpp | 99 ++++++++++--------- .../openPMD/backend/MeshRecordComponent.hpp | 11 ++- .../openPMD/backend/PatchRecordComponent.hpp | 15 ++- include/openPMD/backend/Writable.hpp | 2 +- 6 files changed, 73 insertions(+), 60 deletions(-) diff --git a/include/openPMD/RecordComponent.hpp b/include/openPMD/RecordComponent.hpp index a08e668229..b2fa96c7d5 100644 --- a/include/openPMD/RecordComponent.hpp +++ b/include/openPMD/RecordComponent.hpp @@ -137,7 +137,7 @@ class RecordComponent : public BaseRecordComponent friend class Container; friend class Iteration; friend class ParticleSpecies; - template< typename T_elem > + template< typename T_elem, typename T_RecordComponent > friend class BaseRecord; template< typename T_elem > friend class BaseRecordInterface; diff --git a/include/openPMD/backend/Attributable.hpp b/include/openPMD/backend/Attributable.hpp index 111550458f..c13e2f23d7 100644 --- a/include/openPMD/backend/Attributable.hpp +++ b/include/openPMD/backend/Attributable.hpp @@ -110,7 +110,7 @@ attr_value_check( std::string const key, std::string const value ) "' must not be empty!" ); } -template< typename > class BaseRecordData; +template< typename, typename > class BaseRecordData; } // namespace internal /** @brief Layer to manage storage of attributes associated with file objects. @@ -123,7 +123,7 @@ class Attributable // @todo remove unnecessary friend (wew that sounds bitter) using A_MAP = std::map< std::string, Attribute >; friend Writable* getWritable(Attributable*); - template< typename T_elem > + template< typename T_elem, typename T_RecordComponent > friend class BaseRecord; template< typename T_elem > friend class BaseRecordInterface; diff --git a/include/openPMD/backend/BaseRecord.hpp b/include/openPMD/backend/BaseRecord.hpp index 6ae5fd96ed..7f7377c8a9 100644 --- a/include/openPMD/backend/BaseRecord.hpp +++ b/include/openPMD/backend/BaseRecord.hpp @@ -51,9 +51,9 @@ namespace detail namespace internal { - template< typename T_elem > + template< typename T_elem, typename T_RecordComponentData > class BaseRecordData - : public detail::ContainerDataWithBase< T_elem, RecordComponentData > + : public detail::ContainerDataWithBase< T_elem, T_RecordComponentData > { public: /** @@ -62,7 +62,7 @@ namespace internal * and the last hierarchical layer is skipped (i.e. only one OPEN_PATH * task for Record and RecordComponent). */ - bool m_containsScalar = false; + bool m_containsScalar = false; // rename to m_isScalar BaseRecordData(); @@ -84,32 +84,34 @@ namespace internal * We specify the above concept by BaseRecord instead and use the * auxiliary::OkOr class template to treat the void type specially. */ -template< typename T_elem_maybe_void > +template< + typename T_elem_maybe_void, typename T_RecordComponent = T_elem_maybe_void > class BaseRecord : public detail::ContainerWithBase< - typename auxiliary::OkOr< T_elem_maybe_void, BaseRecord< void > >::type, - RecordComponent > + typename auxiliary::OkOr< + T_elem_maybe_void, BaseRecord< void, T_RecordComponent > >::type, + T_RecordComponent > { using T_elem = - typename auxiliary::OkOr< T_elem_maybe_void, BaseRecord< void > >::type; - using T_container = detail::ContainerWithBase< - typename auxiliary::OkOr< T_elem_maybe_void, BaseRecord< void > >::type, - RecordComponent >; + typename auxiliary::OkOr< + T_elem_maybe_void, BaseRecord< void, T_RecordComponent > >::type; + using T_container = detail::ContainerWithBase< T_elem, T_RecordComponent >; friend class Iteration; friend class ParticleSpecies; friend class PatchRecord; friend class Record; friend class Mesh; - std::shared_ptr< internal::BaseRecordData< T_elem > > m_baseRecordData{ - new internal::BaseRecordData< T_elem >() }; + using DataClass = internal::BaseRecordData< + T_elem, typename T_RecordComponent::DataClass >; + std::shared_ptr< DataClass > m_baseRecordData{ new DataClass() }; - inline internal::BaseRecordData< T_elem > & get() + inline DataClass & get() { return *m_baseRecordData; } - inline internal::BaseRecordData< T_elem > const & get() const + inline DataClass const & get() const { return *m_baseRecordData; } @@ -118,9 +120,9 @@ class BaseRecord : protected: - BaseRecord( std::shared_ptr< internal::BaseRecordData< T_elem > > ); + BaseRecord( std::shared_ptr< DataClass > ); - inline void setData( internal::BaseRecordData< T_elem > * data ) + inline void setData( std::shared_ptr< DataClass > data ) { m_baseRecordData = std::move( data ); T_container::setData( m_baseRecordData ); @@ -174,13 +176,12 @@ class BaseRecord : bool scalar() const; protected: - BaseRecord( internal::BaseRecordData< T_elem > * ); void readBase(); private: void flush(std::string const&) final; virtual void flush_impl(std::string const&) = 0; - virtual void read() override = 0; + virtual void read() = 0; /** * @brief Check recursively whether this BaseRecord is dirty. @@ -198,8 +199,8 @@ class BaseRecord : namespace internal { - template< typename T_elem > - BaseRecordData< T_elem >::BaseRecordData() + template< typename T_elem, typename T_RecordComponentData > + BaseRecordData< T_elem, T_RecordComponentData >::BaseRecordData() { Attributable impl{ { this, []( auto const * ){} } }; impl.setAttribute( @@ -208,23 +209,24 @@ namespace internal } } // namespace internal -template< typename T_elem > -BaseRecord< T_elem >::BaseRecord() : T_container{ nullptr } +template< typename T_elem, typename T_RecordComponent > +BaseRecord< T_elem, T_RecordComponent >::BaseRecord() : T_container{ nullptr } { T_container::setData( m_baseRecordData ); } -template< typename T_elem > -BaseRecord< T_elem >::BaseRecord( - std::shared_ptr< internal::BaseRecordData< T_elem > > data ) +template< typename T_elem, typename T_RecordComponent > +BaseRecord< T_elem, T_RecordComponent >::BaseRecord( + std::shared_ptr< DataClass > data ) : T_container{ data } , m_baseRecordData{ std::move( data ) } { } -template< typename T_elem > -inline typename BaseRecord< T_elem >::mapped_type & -BaseRecord< T_elem >::operator[]( key_type const & key ) +template< typename T_elem, typename T_RecordComponent > +inline auto +BaseRecord< T_elem, T_RecordComponent >::operator[]( key_type const & key ) +-> mapped_type & { auto it = this->find(key); if( it != this->end() ) @@ -246,9 +248,10 @@ BaseRecord< T_elem >::operator[]( key_type const & key ) } } -template< typename T_elem > -inline typename BaseRecord< T_elem >::mapped_type& -BaseRecord< T_elem >::operator[](key_type&& key) +template< typename T_elem, typename T_RecordComponent > +inline auto +BaseRecord< T_elem, T_RecordComponent >::operator[](key_type&& key) +-> mapped_type& { auto it = this->find(key); if( it != this->end() ) @@ -270,9 +273,10 @@ BaseRecord< T_elem >::operator[](key_type&& key) } } -template< typename T_elem > -inline typename BaseRecord< T_elem >::size_type -BaseRecord< T_elem >::erase(key_type const& key) +template< typename T_elem, typename T_RecordComponent > +inline auto +BaseRecord< T_elem, T_RecordComponent >::erase(key_type const& key) +-> size_type { bool const keyScalar = (key == RecordComponent::SCALAR); size_type res; @@ -300,9 +304,10 @@ BaseRecord< T_elem >::erase(key_type const& key) return res; } -template< typename T_elem > -inline typename BaseRecord< T_elem >::iterator -BaseRecord< T_elem >::erase(iterator res) +template< typename T_elem, typename T_RecordComponent > +inline auto +BaseRecord< T_elem, T_RecordComponent >::erase(iterator res) +-> iterator { bool const keyScalar = (res->first == RecordComponent::SCALAR); iterator ret; @@ -330,23 +335,23 @@ BaseRecord< T_elem >::erase(iterator res) return ret; } -template< typename T_elem > +template< typename T_elem, typename T_RecordComponent > inline std::array< double, 7 > -BaseRecord< T_elem >::unitDimension() const +BaseRecord< T_elem, T_RecordComponent >::unitDimension() const { return this->getAttribute("unitDimension").template get< std::array< double, 7 > >(); } -template< typename T_elem > +template< typename T_elem, typename T_RecordComponent > inline bool -BaseRecord< T_elem >::scalar() const +BaseRecord< T_elem, T_RecordComponent >::scalar() const { return get().m_containsScalar; } -template< typename T_elem > +template< typename T_elem, typename T_RecordComponent > inline void -BaseRecord< T_elem >::readBase() +BaseRecord< T_elem, T_RecordComponent >::readBase() { using DT = Datatype; Parameter< Operation::READ_ATT > aRead; @@ -383,9 +388,9 @@ BaseRecord< T_elem >::readBase() throw std::runtime_error("Unexpected Attribute datatype for 'timeOffset'"); } -template< typename T_elem > +template< typename T_elem, typename T_RecordComponent > inline void -BaseRecord< T_elem >::flush(std::string const& name) +BaseRecord< T_elem, T_RecordComponent >::flush(std::string const& name) { if( !this->written() && this->empty() ) throw std::runtime_error("A Record can not be written without any contained RecordComponents: " + name); @@ -395,9 +400,9 @@ BaseRecord< T_elem >::flush(std::string const& name) // method doesn't do it } -template< typename T_elem > +template< typename T_elem, typename T_RecordComponent > inline bool -BaseRecord< T_elem >::dirtyRecursive() const +BaseRecord< T_elem, T_RecordComponent >::dirtyRecursive() const { if( this->dirty() ) { diff --git a/include/openPMD/backend/MeshRecordComponent.hpp b/include/openPMD/backend/MeshRecordComponent.hpp index 7e45b26187..805f9955fc 100644 --- a/include/openPMD/backend/MeshRecordComponent.hpp +++ b/include/openPMD/backend/MeshRecordComponent.hpp @@ -37,11 +37,20 @@ class MeshRecordComponent : public RecordComponent > friend class Container; - friend class Mesh; + template< typename, typename > + friend class BaseRecord; private: + using DataClass = RecordComponent::DataClass; + MeshRecordComponent(); + + // parent-class constructor + MeshRecordComponent( std::shared_ptr< DataClass > data ) + : RecordComponent{ std::move( data ) } + {} + void read() override; public: diff --git a/include/openPMD/backend/PatchRecordComponent.hpp b/include/openPMD/backend/PatchRecordComponent.hpp index e497ece0dc..9106abced3 100644 --- a/include/openPMD/backend/PatchRecordComponent.hpp +++ b/include/openPMD/backend/PatchRecordComponent.hpp @@ -69,7 +69,7 @@ class PatchRecordComponent : public BaseRecordComponent typename T_container, typename T_AttributableBase > friend class Container; - template< typename > friend class BaseRecord; + template< typename, typename > friend class BaseRecord; friend class ParticlePatches; friend class PatchRecord; friend class ParticleSpecies; @@ -108,9 +108,9 @@ class PatchRecordComponent : public BaseRecordComponent bool dirtyRecursive() const; - std::shared_ptr< internal::PatchRecordComponentData > - m_patchRecordComponentData{ - new internal::PatchRecordComponentData() }; + using DataClass = internal::PatchRecordComponentData; + + std::shared_ptr< DataClass > m_patchRecordComponentData{ new DataClass() }; PatchRecordComponent(); @@ -118,18 +118,17 @@ class PatchRecordComponent : public BaseRecordComponent PatchRecordComponent( std::shared_ptr< internal::PatchRecordComponentData > ); - inline internal::PatchRecordComponentData const & get() const + inline DataClass const & get() const { return *m_patchRecordComponentData; } - inline internal::PatchRecordComponentData & get() + inline DataClass & get() { return *m_patchRecordComponentData; } - inline void setData( - std::shared_ptr< internal::PatchRecordComponentData > data ) + inline void setData( std::shared_ptr< DataClass > data ) { m_patchRecordComponentData = std::move( data ); BaseRecordComponent::setData( m_patchRecordComponentData ); diff --git a/include/openPMD/backend/Writable.hpp b/include/openPMD/backend/Writable.hpp index 7f5bf09955..0225436292 100644 --- a/include/openPMD/backend/Writable.hpp +++ b/include/openPMD/backend/Writable.hpp @@ -65,7 +65,7 @@ class Writable final { friend class internal::AttributableData; friend class Attributable; - template< typename T_elem > + template< typename T_elem, typename T_RecordComponent > friend class BaseRecord; template< typename T_elem > friend class BaseRecordInterface;