diff --git a/src/pvxs/sharedArray.h b/src/pvxs/sharedArray.h index e5479bf..28cdb0b 100644 --- a/src/pvxs/sharedArray.h +++ b/src/pvxs/sharedArray.h @@ -178,6 +178,9 @@ public: PVXS_API std::ostream& operator<<(std::ostream& strm, const Limiter&); +PVXS_API +void _throw_bad_cast(ArrayType from, ArrayType to); + } // namespace detail /** std::vector-like contigious array of items passed by reference. @@ -379,23 +382,48 @@ public: } #if _DOXYGEN_ - //! Cast to other type, preserving const-ness. + /** Cast to/from void, preserving const-ness. + * + * Allowed casts depend upon two aspects of type parameter E. + * + * Whether the base type is void or non-void. + * And whether or not the const qualifier is present. + * + * Type E may always be cast to itself. + * + * Casts must preseve const-ness. + * Either both of E and TO, or neither, must be const qualified. + * + * At most one of E or TO may have different non-void base type. + */ template shared_array castTo() const; #endif + template{} && (std::is_const{} == std::is_const{}), int>::type =0> + shared_array + castTo() const { + return shared_array(this->_data, this->_data.get(), this->_count); // implied cast to void* + } + + template{}, int>::type =0> + shared_array + castTo() const { + return *this; + } + // static_cast() to non-void, preserving const-ness template{} && (std::is_const{} == std::is_const{}), int>::type =0> shared_array - castTo() const { + castToUnsafe() const { return shared_array(this->_data, static_cast(this->_data.get()), this->_count); } // static_cast() to void, preserving const-ness template{} && (std::is_const{} == std::is_const{}), int>::type =0> shared_array - castTo() const { + castToUnsafe() const { return shared_array(this->_data, this->_data.get(), this->_count); // implied cast to void* } @@ -519,13 +547,29 @@ public: template{} && (std::is_const{} == std::is_const{}), int>::type =0> shared_array castTo() const { + if(this->_data && _type!=detail::CaptureCode::type>::code) { + detail::_throw_bad_cast(_type, detail::CaptureCode::type>::code); + } + return shared_array(this->_data, static_cast(this->_data.get()), this->_count); + } + + template{} && (std::is_const{} == std::is_const{}), int>::type =0> + shared_array + castTo() const { + return *this; + } + + // static_cast() to non-void, preserving const-ness + template{} && (std::is_const{} == std::is_const{}), int>::type =0> + shared_array + castToUnsafe() const { return shared_array(this->_data, static_cast(this->_data.get()), this->_count); } // static_cast() to void, preserving const-ness template{} && (std::is_const{} == std::is_const{}), int>::type =0> shared_array - castTo() const { + castToUnsafe() const { // in reality this is either void -> void, or const void -> const void // aka. simple copy return *this; diff --git a/src/util.cpp b/src/util.cpp index 9010164..854fd14 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -203,6 +203,11 @@ std::ostream& operator<<(std::ostream& strm, const Limiter& lim) return strm; } +void _throw_bad_cast(ArrayType from, ArrayType to) +{ + throw std::logic_error(SB()<<"Unable to cast array from "< Void; + + (void)Void.castTo(); + (void)Void.castTo(); + // not allowed + //(void)Void.castTo(); + //(void)Void.castTo(); + + shared_array CVoid; + + (void)CVoid.castTo(); + (void)CVoid.castTo(); + // not allowed + //(void)CVoid.castTo(); + //(void)CVoid.castTo(); + + shared_array Int; + + (void)Int.castTo(); + (void)Int.castTo(); + // not allowed + //(void)Int.castTo(); + //(void)Int.castTo(); + + shared_array CInt; + + (void)CInt.castTo(); + (void)CInt.castTo(); + // not allowed + //(void)CInt.castTo(); + //(void)CInt.castTo(); + + shared_array Double({1.0, 2.0}); + Void = Double.castTo(); + testThrows([&Void](){ + (void)Void.castTo(); + })<<"Attempt cast to wrong type"; + + Void.clear(); + // now doesn't throw + (void)Void.castTo(); +} + } // namespace MAIN(testshared) { - testPlan(93); + testPlan(94); testEmpty(); testEmpty(); testEmpty(); @@ -151,5 +198,6 @@ MAIN(testshared) testFreeze(); testFreezeError(); testComplex(); + testCast(); return testDone(); }