From 468489f14ee2f3ce49a068bfb056d8cf5ad0ad9d 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 | 101 +++++++++--------- .../openPMD/backend/MeshRecordComponent.hpp | 11 +- .../openPMD/backend/PatchRecordComponent.hpp | 17 ++- include/openPMD/backend/Writable.hpp | 2 +- 6 files changed, 75 insertions(+), 62 deletions(-) diff --git a/include/openPMD/RecordComponent.hpp b/include/openPMD/RecordComponent.hpp index f59c997538..765c831af5 100644 --- a/include/openPMD/RecordComponent.hpp +++ b/include/openPMD/RecordComponent.hpp @@ -122,7 +122,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 d0381c1a3f..6b83d1d3e6 100644 --- a/include/openPMD/backend/Attributable.hpp +++ b/include/openPMD/backend/Attributable.hpp @@ -102,7 +102,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. @@ -115,7 +115,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 b92ca20007..9efe4e0884 100644 --- a/include/openPMD/backend/BaseRecord.hpp +++ b/include/openPMD/backend/BaseRecord.hpp @@ -51,12 +51,12 @@ 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: - bool m_containsScalar = false; + bool m_containsScalar = false; // rename to m_isScalar BaseRecordData(); @@ -78,17 +78,18 @@ 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; @@ -97,16 +98,17 @@ class BaseRecord : friend class Mesh; friend class ParticleSpecies; - 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 const_cast< internal::BaseRecordData< T_elem > & >( + return const_cast< DataClass & >( static_cast< BaseRecord const * >( this )->get() ); } - inline internal::BaseRecordData< T_elem > const & get() const + inline DataClass const & get() const { return *m_baseRecordData; } @@ -115,9 +117,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 ); @@ -171,13 +173,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. @@ -195,8 +196,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( @@ -205,23 +206,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() ) @@ -243,9 +245,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() ) @@ -267,9 +270,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; @@ -297,9 +301,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; @@ -327,23 +332,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; @@ -380,9 +385,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); @@ -392,9 +397,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 a6eb2a3464..c95cd338ed 100644 --- a/include/openPMD/backend/PatchRecordComponent.hpp +++ b/include/openPMD/backend/PatchRecordComponent.hpp @@ -66,7 +66,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; @@ -105,9 +105,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(); @@ -115,20 +115,19 @@ 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 const_cast< internal::PatchRecordComponentData & >( + return const_cast< DataClass & >( static_cast< PatchRecordComponent const * >( this ) ->get() ); } - 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;