Utopia 2
Framework for studying models of complex & adaptive systems.
Loading...
Searching...
No Matches
hdfattribute.hh
Go to the documentation of this file.
1
8#ifndef UTOPIA_DATAIO_HDFATTRIBUTE_HH
9#define UTOPIA_DATAIO_HDFATTRIBUTE_HH
10
11#include <cstring>
12#include <functional>
13#include <memory>
14#include <string>
15
16#include <hdf5.h>
17#include <hdf5_hl.h>
18
19#include "hdfbufferfactory.hh"
20#include "hdfdataspace.hh"
21#include "hdfobject.hh"
22#include "hdftype.hh"
23
24namespace Utopia
25{
26namespace DataIO
27{
28
45class HDFAttribute final : public HDFObject< HDFCategory::attribute >
46{
47 private:
51 std::vector< hsize_t > _shape;
52
57
63
69
79 template < typename result_type >
80 void
82 {
83 this->_log->debug("Creating attribute {}", _path);
84
85 _dataspace.open(this->_path + " dataspace", _shape.size(), _shape, {});
86
87 _type.open< result_type >("datatype of " + _path, typesize);
88
89 this->bind_to(H5Acreate2(_parent_identifier.get_id(),
90 _path.c_str(),
92 _dataspace.get_C_id(), // dspace
95 &H5Aclose,
96 _path);
97 }
98
105 template < typename Type >
106 herr_t
108 {
109 this->_log->debug("Writing container data to attribute {} ...", _path);
110 using value_type_1 = typename Type::value_type;
112
113 // we can write directly if we have a plain vector, no nested or
114 // stringtype.
115 if constexpr (std::is_same_v< Type, std::vector< value_type_1 > > and
116 not Utils::is_container_v< value_type_1 > and
117 not Utils::is_string_v< value_type_1 >)
118 {
119 this->_log->debug("... of simple vector type");
120
121 // check if attribute has been created, else do
122 if (get_C_id() == -1)
123 {
125 }
126
127 return H5Awrite(
128 get_C_id(), _type.get_C_id(), attribute_data.data());
129 }
130 // when stringtype or containertype is stored in a container, then
131 // we have to buffer. bufferfactory handles how to do this in detail
132 else
133 {
134 this->_log->debug("... of non-trivial container type");
135 // if we want to write std::arrays then we can use
136 // fixed size array types. Else we use variable length arrays.
137 if constexpr (Utils::is_array_like_v< value_type_1 >)
138 {
139 this->_log->debug("... of fixed size array type");
140 constexpr std::size_t s =
142
143 if (get_C_id() == -1)
144 {
146 }
147
148 auto buffer = HDFBufferFactory::buffer(
149 std::begin(attribute_data),
150 std::end(attribute_data),
151 [](auto& value) -> value_type_1& { return value; });
152
153 return H5Awrite(get_C_id(), _type.get_C_id(), buffer.data());
154 }
155 else
156 {
157 this->_log->debug("... of variable length type");
158 if (get_C_id() == -1)
159 {
161 }
162
163 auto buffer = HDFBufferFactory::buffer(
164 std::begin(attribute_data),
165 std::end(attribute_data),
166 [](auto& value) -> value_type_1& { return value; });
167
168 return H5Awrite(get_C_id(), _type.get_C_id(), buffer.data());
169 }
170 }
171 }
172
173 // Function for writing stringtypes, char*, const char*, std::string
174 template < typename Type >
175 herr_t
177 {
178
179 this->_log->debug("Writing string data to attribute {} ...", _path);
180
181 // Since std::string cannot be written directly,
182 // (only const char*/char* can), a buffer pointer has been added
183 // to handle writing in a clearer way and with less code
184 auto len = 0;
185 const char* buffer = nullptr;
186
187 if constexpr (std::is_pointer_v< Type >) // const char* or char* ->
188 // strlen needed
189 {
190 len = std::strlen(attribute_data);
191 buffer = attribute_data;
192 }
193 else // simple for strings
194 {
195 len = attribute_data.size();
196 buffer = attribute_data.c_str();
197 }
198
199 // check if attribute has been created, else do
200 if (get_C_id() == -1)
201 {
203 }
204
205 // use that strings store data in consecutive memory
206 return H5Awrite(get_C_id(), _type.get_C_id(), buffer);
207 }
208
209 // Function for writing pointer types, shape of the array has to be given
210 // where shape means the same as in python
211 template < typename Type >
212 herr_t
214 {
215 this->_log->debug("Writing pointer data to attribute {} ...", _path);
216
217 // result types removes pointers, references, and qualifiers
219
220 if (get_C_id() == -1)
221 {
223 }
224
226 }
227
228 // function for writing a scalartype.
229 template < typename Type >
230 herr_t
232 {
233 this->_log->debug("Writing scalar data to attribute {} ...", _path);
234
235 // because we just write a scalar, the shape tells basically that
236 // the attribute is pointlike: 1D and 1 entry.
237 if (get_C_id() == -1)
238 {
240 }
241
242 return H5Awrite(get_C_id(), _type.get_C_id(), &attribute_data);
243 }
244
245 // Container reader.
246 // We could want to read into a predefined buffer for some reason (frequent
247 // reads), and thus this and the following functions expect an argument
248 // 'buffer' to store their data in. The function 'read(..)' is then
249 // overloaded to allow for automatic buffer creation or a buffer argument.
250 template < typename Type >
251 herr_t
253 {
254
255 this->_log->debug("Reading container data from attribute {} ...",
256 _path);
257
258 using value_type_1 =
260
261 // when the value_type of Type is a container again, we want nested
262 // arrays basically. Therefore we have to check if the desired type
263 // Type is suitable to hold them, read the nested data into a hvl_t
264 // container, assuming that they are varlen because this is the more
265 // general case, and then turn them into the desired type again...
266 if constexpr (Utils::is_container_v< value_type_1 >)
267 {
268 using value_type_2 =
270
271 // if we have nested containers of depth larger than 2, throw a
272 // runtime error because we cannot handle this
273 // TODO extend this to work more generally
274 if constexpr (Utils::is_container_v< value_type_2 >)
275 {
276 throw std::runtime_error(
277 "Cannot read data into nested containers with depth > 3 "
278 "in attribute " +
279 _path + " into vector containers!");
280 }
281
282 // everything is fine.
283
284 // check if type given in the buffer is std::array.
285 // If it is, the user knew that the data stored there
286 // has always the same length, otherwise she does not
287 // know and thus it is assumed that the data is variable
288 // length.
289 if constexpr (Utils::is_array_like_v< value_type_1 >)
290 {
291 this->_log->debug("... of fixed size array type");
292 return H5Aread(get_C_id(), _type.get_C_id(), buffer.data());
293 }
294 else
295 {
296 this->_log->debug("... of variable size type");
297
298 std::vector< hvl_t > temp_buffer(buffer.size());
299
300 herr_t err =
302
303 // turn the varlen buffer into the desired type
304 // Cumbersome, but necessary...
305
306 this->_log->debug("... turning read data into desired type");
307
308 for (std::size_t i = 0; i < buffer.size(); ++i)
309 {
310 buffer[i].resize(temp_buffer[i].len);
311 for (std::size_t j = 0; j < temp_buffer[i].len; ++j)
312 {
313 buffer[i][j] =
314 static_cast< value_type_2* >(temp_buffer[i].p)[j];
315 }
316 }
317
318 #if H5_VERSION_GE(1, 12 , 0)
322 temp_buffer.data());
323 #else
327 temp_buffer.data());
328 #endif
329
330 if (status < 0)
331 {
332 throw std::runtime_error("Error, something went wrong while reading in " + _path + " while reclaiming vlen memory");
333 }
334 // return shape and buffer. Expect to use structured bindings
335 // to extract that later
336 return err;
337 }
338 }
339 else // no nested container, but one containing simple types
340 {
341 if constexpr (!std::is_same_v< std::vector< value_type_1 >, Type >)
342 {
343 throw std::runtime_error("Can only read data from " + _path +
344 " into vector containers!");
345 }
346 else
347 {
348 // when strings are desired to be stored as value_types of the
349 // container, we need to treat them a bit differently,
350 // because hdf5 cannot read directly to them.
351 if constexpr (Utils::is_string_v< value_type_1 >)
352 {
353 this->_log->debug("... of string type");
354
355 std::vector< char* > temp_buffer(buffer.size());
356
358 get_C_id(), _type.get_C_id(), temp_buffer.data());
359
360 // turn temp_buffer into the desired datatype and return
361 for (std::size_t i = 0; i < buffer.size(); ++i)
362 {
363 buffer[i] = temp_buffer[i];
364 }
365
366 // reclaim memory from the temp_buffer, because
367 // the char* therein are allocated by hdf5, but not freed
368 for (auto&& c: temp_buffer)
369 {
370 free(c);
371 }
372
373 return err;
374 }
375 else // others are straight forward
376 {
377 this->_log->debug("... of scalar type");
378
379 return H5Aread(get_C_id(), _type.get_C_id(), buffer.data());
380 }
381 }
382 }
383 }
384
385 // read attirbute data which contains a single string.
386 // this is always read into std::strings, and hence
387 // we can use 'resize'
388 template < typename Type >
389 auto
391 {
392
393 this->_log->debug("Reading string type from attribute {}", _path);
394
395 // resize buffer to the size of the type
396 buffer.resize(_type.size());
397
398 // read data
399 return H5Aread(get_C_id(), _type.get_C_id(), buffer.data());
400 }
401
402 // read pointertype. Either this is given by the user, or
403 // it is assumed to be 1d, thereby flattening Nd attributes
404 template < typename Type >
405 auto
407 {
408 this->_log->debug("Reading pointer type from attribute {}", _path);
409
410 return H5Aread(get_C_id(), _type.get_C_id(), buffer);
411 }
412
413 // read scalar type, trivial
414 template < typename Type >
415 auto
417 {
418 this->_log->debug("Reading scalar type from attribute {}", _path);
419
420 return H5Aread(get_C_id(), _type.get_C_id(), &buffer);
421 }
422
423 public:
429
435 void
437 {
438 using std::swap;
440 swap(static_cast< Base& >(*this), static_cast< Base& >(other));
441 swap(_shape, other._shape);
442 swap(_parent_identifier, other._parent_identifier);
443 swap(_dataspace, other._dataspace);
444 }
445
453 {
454 return _dataspace;
455 }
456
462 auto
464 {
465 return _type;
466 }
467
475 {
476 return _parent_identifier;
477 }
478
482 void
484 {
485 _type.close();
487 _shape.resize(0);
489
491
492 if (is_valid())
493 {
494 Base::close();
495 }
496 }
497
503 auto
505 {
506 // the below is done to retain vector type for _shape member,
507 // which otherwise would break interface due to type change.
508 auto shape = _dataspace.size();
509 _shape.assign(shape.begin(), shape.end());
510
511 return _shape;
512 }
513
520 template < HDFCategory cat >
521 void
522 open(const HDFObject< cat >& parent, std::string name)
523 {
524 this->_log->debug(
525 "Opening attribute named {} in object {}", name, parent.get_path());
526 open(parent.get_id_object(), name);
527 }
528
535 void
536 open(const HDFIdentifier& parent, std::string name)
537 {
538 // update members
540
541 _path = name;
542
543 if (parent.is_valid())
544 {
545
547 _path.c_str()) == 1)
548 {
549 this->_log->debug("... attribute exists already, opening");
550 // attribute exists, open
551 bind_to(H5Aopen(_parent_identifier.get_id(),
552 _path.c_str(),
554 &H5Aclose,
555 name);
556
557 _type.open(*this);
558
559 // README (regarding usage of this in constructors): the usage
560 // of *this is save here, because we always have a valid object
561 // of type HDFDataspace even in ctor given that this is neither
562 // a derived class nor we call a virtual function
563 _dataspace.open(*this);
564 get_shape();
565 }
566 else
567 {
568 this->_log->debug("... attribute does not yet exist, have to "
569 "wait for incoming data to build it");
570
571 this->_id = HDFIdentifier();
572 }
573 }
574 else
575 {
576 throw std::invalid_argument(
577 "Parent object of attribute '" + _path +
578 "' is invalid! Has it been closed already or not been opened "
579 "yet?");
580 }
581 }
582
607 template < typename Type >
608 auto
610 {
611 this->_log->debug("Reading attribute {}", _path);
612
613 if (_shape.size() == 0)
614 {
615 get_shape();
616 }
617
618 // Read can only be done in 1d, and this loop takes care of
619 // computing a 1d size which can accomodate all elements.
620 // This is then passed to the container holding the elements in the end.
621 std::size_t size = 1;
622 for (auto& value : _shape)
623 {
624 size *= value;
625 }
626
627 // type to read in is a container type, which can hold containers
628 // themselvels or just plain types.
629 if constexpr (Utils::is_container_v< Type >)
630 {
631 Type buffer(size);
632 herr_t err = __read_container__(buffer);
633 if (err < 0)
634 {
635 throw std::runtime_error("Error in reading data from " + _path +
636 " into container types");
637 }
638
639 return std::make_tuple(_shape, buffer);
640 }
641 else if constexpr (Utils::is_string_v< Type >) // we can have string
642 // types too, i.e. char*,
643 // const char*,
644 // std::string
645 {
646 std::string buffer; // resized in __read_stringtype__ because this
647 // as a scalar
649 if (err < 0)
650 {
651 throw std::runtime_error("Error in reading data from " + _path +
652 " into stringtype");
653 }
654
655 return std::make_tuple(_shape, buffer);
656 }
657 else if constexpr (std::is_pointer_v< Type > &&
658 !Utils::is_string_v< Type >)
659 {
660 std::shared_ptr< Utils::remove_qualifier_t<Type> > buffer(
661 new Utils::remove_qualifier_t<Type>[size], std::default_delete<Utils::remove_qualifier_t<Type>[]>());
662
663 herr_t err = __read_pointertype__(buffer.get());
664 if (err < 0)
665 {
666 throw std::runtime_error("Error in reading data from " + _path +
667 " into pointertype");
668 }
669 return std::make_tuple(_shape, buffer);
670 }
671 else // reading scalar types is simple enough
672 {
673 Type buffer(0);
675 if (err < 0)
676 {
677 throw std::runtime_error("Error in reading data from " + _path +
678 " into scalar");
679 }
680 return std::make_tuple(_shape, buffer);
681 }
682 }
683
693 template < typename Type >
694 void
695 read(Type& buffer)
696 {
697 this->_log->debug("Reading attribute {} into given buffer", _path);
698
699 if (_shape.size() == 0)
700 {
701 get_shape();
702 }
703
704 // type to read in is a container type, which can hold containers
705 // themselvels or just plain types.
706 if constexpr (Utils::is_container_v< Type >)
707 {
708 // needed to make sure that the buffer has the correct size
709
710 std::size_t size = 1;
711 for (auto& value : _shape)
712 {
713 size *= value;
714 }
715
716 if (buffer.size() != size)
717 {
718 buffer.resize(size);
719 }
720
721 herr_t err = __read_container__(buffer);
722 if (err < 0)
723 {
724 throw std::runtime_error("Error in reading data from " + _path +
725 " into container types");
726 }
727 }
728 else if constexpr (Utils::is_string_v< Type >) // we can have string
729 // types too, i.e. char*,
730 // const char*,
731 // std::string
732 {
733 // resized in __read_stringtype__ because this as a scalar
735 if (err < 0)
736 {
737 throw std::runtime_error("Error in reading data from " + _path +
738 " into stringtype");
739 }
740 }
741 else if constexpr (std::is_pointer_v< Type > &&
742 !Utils::is_string_v< Type >)
743 {
745
746 if (err < 0)
747 {
748 throw std::runtime_error("Error in reading data from " + _path +
749 " into pointertype");
750 }
751 }
752 else // reading scalar types is simple enough
753 {
755 if (err < 0)
756 {
757 throw std::runtime_error("Error in reading data from " + _path +
758 " into scalar");
759 }
760 }
761 }
762
778 template < typename Type >
779 void
780 write(Type attribute_data, std::vector< hsize_t > shape = {})
781 {
782 this->_log->debug("Writing data to attribute {}", _path);
783
784 // check if we have a container. Writing containers requires further
785 // t tests, plain old data can be written right away
786
787 if constexpr (Utils::is_container_v< Type >) // container type
788 {
789 // get the shape from the data. This function is written such
790 // that it writes always 1d, unless a pointer type with different
791 // shape is given.
792 if (_shape.size() == 0)
793 {
794 _shape = { attribute_data.size() };
795 }
796 else
797 {
798 _shape = shape;
799 }
801
802 if (err < 0)
803 {
804 throw std::runtime_error(
805 "An error occurred while writing a containertype to "
806 "attribute " +
807 _path + "!");
808 }
809 }
810 // write string types, i.e. const char*, char*, std::string
811 // These are not containers but not normal scalars either,
812 // so they have to be treated separatly
813 else if constexpr (Utils::is_string_v< Type >)
814 {
815 _shape = { 1 };
816
818
819 if (err < 0)
820 {
821 throw std::runtime_error(
822 "An error occurred while writing a stringtype to "
823 "attribute " +
824 _path + "!");
825 }
826 }
827 // We can also write pointer types, but then the shape of the array
828 // has to be given explicitly. This does not handle stringtypes,
829 // even though const char* /char* are pointer types
830 else if constexpr (std::is_pointer_v< Type > &&
831 !Utils::is_string_v< Type >)
832 {
833 if (shape.size() == 0)
834 {
835 throw std::runtime_error(
836 "Attribute: " + _path +
837 ","
838 "The shape parameter has to be given for pointers "
839 "because "
840 "it cannot be determined automatically");
841 }
842 else
843 {
844 _shape = shape;
845 }
846
848
849 if (err < 0)
850 {
851 throw std::runtime_error(
852 "An error occurred while writing a pointertype/plain array "
853 "to "
854 "attribute " +
855 _path + "!");
856 }
857 }
858 // plain scalar types are treated in a straight forward way
859 else
860 {
861 _shape = { 1 };
862
864 if (err < 0)
865 {
866 throw std::runtime_error(
867 "An error occurred while writing a scalar "
868 "to "
869 "attribute " +
870 _path + "!");
871 }
872 }
873 }
874
887 template < typename Iter, typename Adaptor >
888 void
890 Iter begin,
891 Iter end,
892 Adaptor adaptor = [](auto& value) { return value; },
893 [[maybe_unused]] std::vector< hsize_t > shape = {})
894 {
895 this->_log->debug("Writing data from iterator range to attribute {}",
896 _path);
897
898 using Type = Utils::remove_qualifier_t< decltype(adaptor(*begin)) >;
899 // if we copy only the content of [begin, end), then simple vector
900 // copy suffices
901 if constexpr (std::is_same< Type, typename Iter::value_type >::value)
902 {
903 write(std::vector< Type >(begin, end));
904 }
905 else
906 {
907
908 std::vector< Type > buff(std::distance(begin, end));
909 std::generate(buff.begin(), buff.end(), [&begin, &adaptor]() {
910 return adaptor(*(begin++));
911 });
912
913 write(buff, shape);
914 }
915 }
916
921 HDFAttribute() = default;
922
928 HDFAttribute(const HDFAttribute& other) = default;
929
936
945 operator=(const HDFAttribute& other) = default;
946
960 {
961 close();
962 }
963
971 template < HDFCategory cat >
972 HDFAttribute(const HDFObject< cat >& object, std::string name) :
973 _shape(std::vector< hsize_t >())
974 {
975 open(object, name);
976 }
977};
978
987void
989{
990 lhs.swap(rhs);
991}
992
// end of group HDF5 // end of group DataIO
995
996} // namespace DataIO
997} // namespace Utopia
998#endif
Class for hdf5 attribute, which can be attached to groups and datasets.
Definition hdfattribute.hh:46
virtual ~HDFAttribute()
Destructor.
Definition hdfattribute.hh:959
void close()
closes the attribute
Definition hdfattribute.hh:483
HDFType _type
type done in the HDFAttribute
Definition hdfattribute.hh:68
auto __read_pointertype__(Type buffer)
Definition hdfattribute.hh:406
herr_t __read_container__(Type &buffer)
Definition hdfattribute.hh:252
HDFAttribute(const HDFObject< cat > &object, std::string name)
Constructor for attribute.
Definition hdfattribute.hh:972
HDFAttribute & operator=(const HDFAttribute &other)=default
Copy assignment operator.
auto __read_scalartype__(Type &buffer)
Definition hdfattribute.hh:416
HDFIdentifier get_parent_id()
Get the hdf5 identifier to which the attribute belongs.
Definition hdfattribute.hh:474
void __create_attribute__(hsize_t typesize=0)
private helper function for creation of attribute
Definition hdfattribute.hh:81
herr_t __write_stringtype__(Type attribute_data)
Definition hdfattribute.hh:176
auto read()
Reads data from attribute, and returns the data and its shape in the form of a hsize_t vector.
Definition hdfattribute.hh:609
void open(const HDFObject< cat > &parent, std::string name)
Open a new attribute on HDFObject 'parent' with name 'name'.
Definition hdfattribute.hh:522
void open(const HDFIdentifier &parent, std::string name)
Open a new attribute on HDFObject 'parent' with name 'name'.
Definition hdfattribute.hh:536
HDFDataspace get_filespace()
Get the file-dataspace object.
Definition hdfattribute.hh:452
HDFAttribute(const HDFAttribute &other)=default
Copy constructor.
auto get_shape()
Get the shape object.
Definition hdfattribute.hh:504
auto __read_stringtype__(Type &buffer)
Definition hdfattribute.hh:390
void swap(HDFAttribute &other)
Exchange states between caller and argument.
Definition hdfattribute.hh:436
void write(Type attribute_data, std::vector< hsize_t > shape={})
Function for writing data to the attribute.
Definition hdfattribute.hh:780
HDFAttribute(HDFAttribute &&other)=default
Move constructor.
std::vector< hsize_t > _shape
size of the attributes dataspace
Definition hdfattribute.hh:51
herr_t __write_pointertype__(Type attribute_data)
Definition hdfattribute.hh:213
HDFIdentifier _parent_identifier
Identifier of the parent object.
Definition hdfattribute.hh:56
herr_t __write_container__(Type attribute_data)
Function for writing containers as attribute.
Definition hdfattribute.hh:107
herr_t __write_scalartype__(Type attribute_data)
Definition hdfattribute.hh:231
void read(Type &buffer)
Reads data from attribute into a predefined buffer, and returns the data and its shape in the form of...
Definition hdfattribute.hh:695
HDFDataspace _dataspace
Dataspace object that manages topology of data written and read.
Definition hdfattribute.hh:62
HDFAttribute & operator=(HDFAttribute &&other)=default
Attribute move assignment operator.
auto get_type()
Get the type object.
Definition hdfattribute.hh:463
HDFAttribute()=default
Default constructor, deleted because of reference member.
void write(Iter begin, Iter end, Adaptor adaptor=[](auto &value) { return value;}, std::vector< hsize_t > shape={})
Function for writing data to the attribute.
Definition hdfattribute.hh:889
static auto buffer(Iter begin, Iter end, Adaptor &&adaptor)
static function for turning an iterator range with arbitrarty datatypes into a vector of data as retu...
Definition hdfbufferfactory.hh:96
Class that wraps an HDF5 dataspace and takes care of managing its resources.
Definition hdfdataspace.hh:37
Wrapper class around an hdf5 identifier, used to manage reference counts of the object this identifie...
Definition hdfidentifier.hh:29
void close()
Close the identifier and render the C-Level id held invalid.
Definition hdfidentifier.hh:134
hid_t get_id() const
Get the HDF5 id held by this object.
Definition hdfidentifier.hh:53
Common base class for all HDF5 classes in the DATAIO Module i.e., for all classes that wrap HDF5-C-Li...
Definition hdfobject.hh:37
std::string _path
Name of the object.
Definition hdfobject.hh:50
void close()
Close function which takes care of correctly closing the object and managing the reference counter.
Definition hdfobject.hh:161
virtual bool is_valid() const
Check if the object is still valid.
Definition hdfobject.hh:143
std::shared_ptr< spdlog::logger > _log
pointer to the logger for dataio
Definition hdfobject.hh:56
HDFIdentifier _id
Identifier object that binds an instance of this class to an HDF5 object.
Definition hdfobject.hh:44
hid_t get_C_id() const
Get the C id object.
Definition hdfobject.hh:120
void bind_to(hid_t id, std::function< herr_t(hid_t) > closing_func, std::string path={})
Open the object and bind it to a HDF5 object identified by 'id' with name 'path'. Object should be cr...
Definition hdfobject.hh:186
Class which handles the conversion of C-types into hdf5types.
Definition hdftype.hh:136
void open(T &&object)
Open the HDF5 type associated with an HDFObject, i.e., a dataset or an attribute.
Definition hdftype.hh:224
void close()
Construct close from the given arguments.
Definition hdftype.hh:322
std::size_t size() const
Size of the type held in bytes.
Definition hdftype.hh:210
void swap(WriteTask< BGB, DW, DB, AWG, AWD > &lhs, WriteTask< BGB, DW, DB, AWG, AWD > &rhs)
Swaps the state of lhs and rhs.
Definition write_task.hh:240
Container select_entities(const Manager &mngr, const DataIO::Config &sel_cfg)
Select entities according to parameters specified in a configuration.
Definition select.hh:213
arma::Row< hsize_t > size()
Get the current size of the dataspace in each dimension.
Definition hdfdataspace.hh:94
void open()
Open the dataspace - set it to be equivalent to any data that later will be used to write or read.
Definition hdfdataspace.hh:117
In this file, a class for automatically creating intermediate buffer data structures between the user...
This file provides a class which is responsible for the automatic conversion between C/C++ types and ...
typename remove_qualifier< T >::type remove_qualifier_t
Shorthand for 'typename remove_qualifier::value'.
Definition type_traits.hh:97
Definition agent.hh:11
Definition parallel.hh:235
Return the size of a Type T containing other types at compile time. If no object for which an overloa...
Definition type_traits.hh:438