Skip to content

Commit 4da295b

Browse files
authored
Merge pull request #345 from ax3l/topic-getAttributeCast
Attribute: Implement get<>() Cast
2 parents d3228d7 + f67e00e commit 4da295b

File tree

9 files changed

+82
-144
lines changed

9 files changed

+82
-144
lines changed

CHANGELOG.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Bug Fixes
2323
- Refactor type system and ``Attribute`` set/get
2424
- integers #337
2525
- support ``long double`` reads on MSVC #184
26+
- make ``::get`` cast if convertible #345
2627
- ``setAttribute``: explicit C-string handling #341
2728
- ``Dataset``: ``setCompression`` warning and error logic #326
2829
- avoid impact on unrelated classes in invasive tests #324

include/openPMD/Datatype.hpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,11 @@ isSame( openPMD::Datatype const d, openPMD::Datatype const e )
517517

518518
return false;
519519
}
520+
521+
void
522+
warnWrongDtype(std::string const& key,
523+
Datatype store,
524+
Datatype request);
520525
} // namespace openPMD
521526

522527
#if !defined(_MSC_VER)
@@ -529,12 +534,22 @@ isSame( openPMD::Datatype const d, openPMD::Datatype const e )
529534
* https://stackoverflow.com/questions/44515148/why-is-operator-overload-of-enum-ambiguous-in-msvc
530535
*
531536
* @see openPMD::isSame
537+
*
538+
* @{
532539
*/
533540
inline bool
534541
operator==( openPMD::Datatype d, openPMD::Datatype e )
535542
{
536543
return openPMD::isSame(d, e);
537544
}
545+
546+
inline bool
547+
operator!=( openPMD::Datatype d, openPMD::Datatype e )
548+
{
549+
return !(d == e);
550+
}
551+
/** @}
552+
*/
538553
#endif
539554

540555
namespace std

include/openPMD/RecordComponent.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ RecordComponent::loadChunk(Offset const& o, Extent const& e, std::shared_ptr< T
156156
for( auto const& dimensionSize : e )
157157
numPoints *= dimensionSize;
158158

159-
T value = getCast< T >(*m_constantValue);
159+
T value = m_constantValue->get< T >();
160160

161161
T* raw_ptr = data.get();
162162
std::fill(raw_ptr, raw_ptr + numPoints, value);

include/openPMD/backend/Attributable.hpp

Lines changed: 2 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -203,12 +203,6 @@ class Attributable
203203
std::shared_ptr< A_MAP > m_attributes;
204204
}; // Attributable
205205

206-
207-
void
208-
warnWrongDtype(std::string const& key,
209-
Datatype store,
210-
Datatype request);
211-
212206
//TODO explicitly instanciate Attributable::setAttribute for all T in Datatype
213207
template< typename T >
214208
inline bool
@@ -244,96 +238,21 @@ Attributable::setAttribute(std::string const& key, char const value[])
244238
return this->setAttribute(key, std::string(value));
245239
}
246240

247-
extern template
248-
float
249-
Attributable::readFloatingpoint(std::string const& key) const;
250-
251-
extern template
252-
double
253-
Attributable::readFloatingpoint(std::string const& key) const;
254-
255-
extern template
256-
long double
257-
Attributable::readFloatingpoint(std::string const& key) const;
258-
259241
template< typename T >
260242
inline T
261243
Attributable::readFloatingpoint(std::string const& key) const
262244
{
263245
static_assert(std::is_floating_point< T >::value, "Type of attribute must be floating point");
264246

265-
T t{0};
266-
Attribute a = getAttribute(key);
267-
Datatype target_dtype = determineDatatype< T >();
268-
if( a.dtype == target_dtype )
269-
t = a.get< T >();
270-
else
271-
{
272-
warnWrongDtype(key, a.dtype, target_dtype);
273-
using DT = Datatype;
274-
switch( a.dtype )
275-
{
276-
case DT::FLOAT:
277-
t = static_cast< T >(a.get< float >());
278-
break;
279-
case DT::DOUBLE:
280-
t = static_cast< T >(a.get< double >());
281-
break;
282-
case DT::LONG_DOUBLE:
283-
t = static_cast< T >(a.get< long double >());
284-
break;
285-
default:
286-
throw std::runtime_error("Unknown floating point datatype.");
287-
}
288-
}
289-
return t;
247+
return getAttribute(key).get< T >();
290248
}
291249

292-
extern template
293-
std::vector< float >
294-
Attributable::readVectorFloatingpoint(std::string const& key) const;
295-
296-
extern template
297-
std::vector< double >
298-
Attributable::readVectorFloatingpoint(std::string const& key) const;
299-
300-
extern template
301-
std::vector< long double >
302-
Attributable::readVectorFloatingpoint(std::string const& key) const;
303-
304250
template< typename T >
305251
inline std::vector< T >
306252
Attributable::readVectorFloatingpoint(std::string const& key) const
307253
{
308254
static_assert(std::is_floating_point< T >::value, "Type of attribute must be floating point");
309255

310-
std::vector< T > vt{};
311-
Attribute a = getAttribute(key);
312-
Datatype target_dtype = determineDatatype< std::vector< T > >();
313-
if( a.dtype == target_dtype )
314-
vt = a.get< std::vector< T > >();
315-
else
316-
{
317-
warnWrongDtype(key, a.dtype, target_dtype);
318-
using DT = Datatype;
319-
switch( a.dtype )
320-
{
321-
case DT::VEC_FLOAT:
322-
for( auto const& val : a.get< std::vector< float > >() )
323-
vt.push_back(static_cast< T >(val));
324-
break;
325-
case DT::VEC_DOUBLE:
326-
for( auto const& val : a.get< std::vector< double > >() )
327-
vt.push_back(static_cast< T >(val));
328-
break;
329-
case DT::VEC_LONG_DOUBLE:
330-
for( auto const& val : a.get< std::vector< long double > >() )
331-
vt.push_back(static_cast< T >(val));
332-
break;
333-
default:
334-
throw std::runtime_error("Unknown floating point datatype.");
335-
}
336-
}
337-
return vt;
256+
return getAttribute(key).get< std::vector< T > >();
338257
}
339258
} // namespace openPMD

include/openPMD/backend/Attribute.hpp

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ namespace openPMD
4545
* @note Extending and/or modifying the available formats requires identical
4646
* modifications to Datatype.
4747
*/
48-
using Attribute = auxiliary::Variant< Datatype,
48+
class Attribute :
49+
public auxiliary::Variant< Datatype,
4950
char, unsigned char, // signed char,
5051
short, int, long, long long,
5152
unsigned short, unsigned int, unsigned long, unsigned long long,
@@ -66,7 +67,24 @@ using Attribute = auxiliary::Variant< Datatype,
6667
std::vector< long double >,
6768
std::vector< std::string >,
6869
std::array< double, 7 >,
69-
bool >;
70+
bool >
71+
{
72+
public:
73+
Attribute(resource r) : Variant(r)
74+
{ }
75+
76+
/** Retrieve a stored specific Attribute and cast if convertible.
77+
*
78+
* @note This performs a static_cast and might introduce precision loss if
79+
* requested. Check dtype explicitly beforehand if needed.
80+
*
81+
* @throw std::runtime_error if stored object is not static castable to U.
82+
* @tparam U Type of the object to be casted to.
83+
* @return Copy of the retrieved object, casted to type U.
84+
*/
85+
template< typename U >
86+
U get() const;
87+
};
7088

7189
template< typename T, typename U, bool isConvertible = std::is_convertible<T, U>::value >
7290
struct DoConvert;
@@ -78,7 +96,6 @@ struct DoConvert<T, U, false>
7896
U operator()( PV )
7997
{
8098
throw std::runtime_error("getCast: no cast possible.");
81-
return U{};
8299
}
83100
};
84101

@@ -116,7 +133,7 @@ struct DoConvert<std::vector< T >, std::vector< U >, false>
116133
}
117134
};
118135

119-
/** Retrieve a stored specific Attribute and cast if possible.
136+
/** Retrieve a stored specific Attribute and cast if convertible.
120137
*
121138
* @throw std::runtime_error if stored object is not static castable to U.
122139
* @tparam U Type of the object to be casted to.
@@ -192,8 +209,12 @@ getCast( Attribute const a )
192209
return DoConvert<bool, U>{}(pvalue_b);
193210
else
194211
throw std::runtime_error("getCast: unknown Datatype.");
212+
}
195213

196-
return U{};
214+
template< typename U >
215+
U Attribute::get() const
216+
{
217+
return getCast< U >( Variant::getResource() );
197218
}
198219

199220
} // namespace openPMD

src/Datatype.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,24 @@
2020
*/
2121
#include "openPMD/Datatype.hpp"
2222

23+
#include <string>
2324
#include <iostream>
2425

2526

27+
namespace openPMD
28+
{
29+
void warnWrongDtype(std::string const& key,
30+
Datatype store,
31+
Datatype request)
32+
{
33+
std::cerr << "Warning: Attribute '" << key
34+
<< "' stored as " << store
35+
<< ", requested as " << request
36+
<< ". Casting unconditionally with possible loss of precision.\n";
37+
}
38+
} // openPMD
39+
40+
2641
std::ostream&
2742
std::operator<<(std::ostream& os, openPMD::Datatype d)
2843
{

src/RecordComponent.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,9 +226,9 @@ RecordComponent::readBase()
226226
// uint64_t check
227227
Datatype const attrDtype = *aRead.dtype;
228228
if( isSame( attrDtype, determineDatatype< uint64_t >() ) )
229-
e.push_back( getCast< uint64_t >( a ) );
229+
e.push_back( a.get< uint64_t >() );
230230
else if( isSame( attrDtype, determineDatatype< std::vector< uint64_t > >() ) )
231-
for( auto const& val : getCast< std::vector< uint64_t > >( a ) )
231+
for( auto const& val : a.get< std::vector< uint64_t > >() )
232232
e.push_back( val );
233233
else
234234
{

src/backend/Attributable.cpp

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -289,39 +289,4 @@ Attributable::linkHierarchy(std::shared_ptr< Writable > const& w)
289289
m_writable->parent = writable;
290290
this->parent = writable;
291291
}
292-
293-
294-
void warnWrongDtype(std::string const& key,
295-
Datatype store,
296-
Datatype request)
297-
{
298-
std::cerr << "Warning: Attribute '" << key
299-
<< "' stored as " << store
300-
<< ", requested as " << request
301-
<< ". Casting unconditionally with possible loss of precision.\n";
302-
}
303-
304-
template
305-
float
306-
Attributable::readFloatingpoint(std::string const& key) const;
307-
308-
template
309-
double
310-
Attributable::readFloatingpoint(std::string const& key) const;
311-
312-
template
313-
long double
314-
Attributable::readFloatingpoint(std::string const& key) const;
315-
316-
template
317-
std::vector< float >
318-
Attributable::readVectorFloatingpoint(std::string const& key) const;
319-
320-
template
321-
std::vector< double >
322-
Attributable::readVectorFloatingpoint(std::string const& key) const;
323-
324-
template
325-
std::vector< long double >
326-
Attributable::readVectorFloatingpoint(std::string const& key) const;
327292
} // openPMD

0 commit comments

Comments
 (0)