diff --git a/include/openPMD/LoadStoreChunk.hpp b/include/openPMD/LoadStoreChunk.hpp index 864b7f9472..c9f2d30eda 100644 --- a/include/openPMD/LoadStoreChunk.hpp +++ b/include/openPMD/LoadStoreChunk.hpp @@ -32,6 +32,12 @@ namespace internal std::optional memorySelection; }; + /* + * Actual data members of `ConfigureLoadStore<>`. They don't depend on the + * template parameter of that class template, so by extracting the members + * to this struct, we can pass them around between different instances of + * the class template. + */ struct ConfigureLoadStoreData { ConfigureLoadStoreData(RecordComponent &); @@ -42,6 +48,13 @@ namespace internal }; } // namespace internal +/** Basic configuration for a Load/Store operation. + * + * @tparam ChildClass CRT pattern. + * The purpose is that in child classes `return *this` should return + * an instance of the child class, not of ConfigureLoadStore. + * Instantiate with void when using without subclass. + */ template class ConfigureLoadStore : protected internal::ConfigureLoadStoreData { @@ -53,7 +66,7 @@ class ConfigureLoadStore : protected internal::ConfigureLoadStoreData ConfigureLoadStore(RecordComponent &rc); ConfigureLoadStore(ConfigureLoadStoreData &&); - auto dim() const -> uint8_t; + [[nodiscard]] auto dim() const -> uint8_t; auto getOffset() -> Offset const &; auto getExtent() -> Extent const &; auto storeChunkConfig() -> internal::LoadStoreConfig; @@ -67,34 +80,37 @@ class ConfigureLoadStore : protected internal::ConfigureLoadStoreData auto offset(Offset) -> return_type &; auto extent(Extent) -> return_type &; + /* + * If the type is non-const, then the return type should be + * ConfigureLoadStoreFromBuffer<>, ... + */ template struct shared_ptr_return_type_impl { - using type = ConfigureLoadStoreFromBuffer< - std::shared_ptr>>; + using type = ConfigureLoadStoreFromBuffer>; }; + /* + * ..., but if it is a const type, Load operations make no sense, so the + * return type should be ConfigureStoreChunkFromBuffer<>. + */ template struct shared_ptr_return_type_impl { using type = ConfigureStoreChunkFromBuffer, void>; }; - template - struct shared_ptr_return_type_impl - { - using type = - ConfigureStoreChunkFromBuffer, void>; - }; template using shared_ptr_return_type = - typename shared_ptr_return_type_impl::type; + typename shared_ptr_return_type_impl>::type; - template - using normalize_dataset_type = std::remove_cv_t>; + /* + * As loading into unique pointer types makes no sense, the case is simpler + * for unique pointers. Just remove the array extents here. + */ template using unique_ptr_return_type = ConfigureStoreChunkFromBuffer< - UniquePtrWithLambda>, + UniquePtrWithLambda>, void>; // @todo rvalue references..? @@ -127,6 +143,19 @@ class ConfigureLoadStore : protected internal::ConfigureLoadStoreData [[nodiscard]] auto enqueueLoadVariant() -> shared_ptr_dataset_types; }; +/** Configuration for a Store operation with a buffer type. + * + * This class does intentionally not support Load operations since there are + * pointer types (const pointers, unique pointers) where Load operations make no + * sense. See the \ref ConfigureLoadStoreFromBuffer class template for both + * Load/Store operations. + * + * @tparam Ptr_Type The type of pointer used internally. + * @tparam ChildClass CRT pattern. + * The purpose is that in child classes `return *this` should return + * an instance of the child class, not of ConfigureStoreChunkFromBuffer. + * Instantiate with void when using without subclass. + */ template class ConfigureStoreChunkFromBuffer : public ConfigureLoadStore parent_t const &; auto enqueueStore() -> void; + + /** This intentionally shadows the parent class's enqueueLoad method in + * order to show a compile error when using enqueueLoad() on an object of + * this class. The parent method can still be accessed through as_parent() + * if needed. + */ template auto enqueueLoad() { @@ -171,6 +206,14 @@ class ConfigureStoreChunkFromBuffer } }; +/** Configuration for a Load/Store operation with a buffer type. + * + * Only instantiated for pointer types where Load operations make sense (e.g. no + * const pointers and no unique pointers). + * \ref ConfigureStoreChunkFromBuffer is used otherwise. + * + * @tparam Ptr_Type The type of pointer used internally. + */ template class ConfigureLoadStoreFromBuffer : public ConfigureStoreChunkFromBuffer< diff --git a/include/openPMD/LoadStoreChunk.tpp b/include/openPMD/LoadStoreChunk.tpp index f91f61b5e0..382d899deb 100644 --- a/include/openPMD/LoadStoreChunk.tpp +++ b/include/openPMD/LoadStoreChunk.tpp @@ -24,13 +24,17 @@ auto ConfigureLoadStore::withUniquePtr(UniquePtrWithLambda data) -> unique_ptr_return_type { + // should we support them? + static_assert( + !std::is_const_v, + "Unique pointers to const types not supported as storeChunk buffers."); if (!data) { throw std::runtime_error( "Unallocated pointer passed during chunk store."); } return unique_ptr_return_type( - std::move(data).template static_cast_>(), + std::move(data).template static_cast_>(), {std::move(*this)}); } template