diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2017-09-08 19:29:04 +0100 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2017-09-10 22:20:42 +0100 |
commit | d17f90c71d4c8703c52c1ea1be383577d7771621 (patch) | |
tree | 74920ee495c4914481c7b8c5850b057034f2a7f4 | |
parent | Don't use ClassType in the optionals test as it has a custom model type which... (diff) | |
download | slicer-d17f90c71d4c8703c52c1ea1be383577d7771621.tar.bz2 slicer-d17f90c71d4c8703c52c1ea1be383577d7771621.tar.xz slicer-d17f90c71d4c8703c52c1ea1be383577d7771621.zip |
Converted Model part now handles optionality internally (cases where it do so quirkily probably still exist)
-rw-r--r-- | slicer/slicer/modelPartsTypes.h | 18 | ||||
-rw-r--r-- | slicer/slicer/modelPartsTypes.impl.h | 82 | ||||
-rw-r--r-- | slicer/tool/parser.cpp | 15 |
3 files changed, 96 insertions, 19 deletions
diff --git a/slicer/slicer/modelPartsTypes.h b/slicer/slicer/modelPartsTypes.h index 904a88a..52b7c62 100644 --- a/slicer/slicer/modelPartsTypes.h +++ b/slicer/slicer/modelPartsTypes.h @@ -62,12 +62,12 @@ namespace Slicer { template<typename ET, typename MT> inline static bool tryConvertFrom(const ValueSourcePtr & vsp, MT * model); template<typename ET, typename MT, typename Conv> - inline static bool tryConvertTo(const ValueTargetPtr & vsp, MT * model, const Conv & conv); + inline static bool tryConvertTo(const ValueTargetPtr & vsp, const MT * model, const Conv & conv); template<typename ET, typename MT> - inline static bool tryConvertTo(const ValueTargetPtr & vsp, MT * model); + inline static bool tryConvertTo(const ValueTargetPtr & vsp, const MT * model); }; - template<typename T, typename MT, typename M, MT M::* MV> + template<typename T, typename M, T M::* MV> class DLL_PUBLIC ModelPartForConverted : public ModelPartForConvertedBase, protected ModelPartModel<T> { public: typedef T element_type; @@ -78,6 +78,18 @@ namespace Slicer { virtual void GetValue(ValueTargetPtr s) override; }; + template<typename T, typename M, IceUtil::Optional<T> M::* MV> + class DLL_PUBLIC ModelPartForConverted<IceUtil::Optional<T>, M, MV> : public ModelPartForConvertedBase, protected ModelPartModel<IceUtil::Optional<T>> { + public: + typedef IceUtil::Optional<T> element_type; + + ModelPartForConverted(IceUtil::Optional<T> * h); + + virtual void SetValue(ValueSourcePtr s) override; + virtual void GetValue(ValueTargetPtr s) override; + virtual bool HasValue() const override; + }; + class DLL_PUBLIC ModelPartForOptionalBase : public ModelPart { public: virtual void OnEachChild(const ChildHandler & ch) override; diff --git a/slicer/slicer/modelPartsTypes.impl.h b/slicer/slicer/modelPartsTypes.impl.h index 1567b63..2d6d169 100644 --- a/slicer/slicer/modelPartsTypes.impl.h +++ b/slicer/slicer/modelPartsTypes.impl.h @@ -163,20 +163,76 @@ namespace Slicer { } // ModelPartForConverted - template<typename T, typename MT, typename M, MT M::* MV> - ModelPartForConverted<T, MT, M, MV>::ModelPartForConverted(T * h) : + template<typename T, typename M, T M::* MV> + ModelPartForConverted<T, M, MV>::ModelPartForConverted(T * h) : ModelPartModel<T>(h) { } + template<typename T, typename M, IceUtil::Optional<T> M::* MV> + ModelPartForConverted<IceUtil::Optional<T>, M, MV>::ModelPartForConverted(IceUtil::Optional<T> * h) : + ModelPartModel<IceUtil::Optional<T>>(h) + { + } + + template<typename T, typename M, IceUtil::Optional<T> M::* MV> + bool ModelPartForConverted<IceUtil::Optional<T>, M, MV>::HasValue() const + { + BOOST_ASSERT(this->Model); + return *this->Model; + } + + // Function traits helpers + template <typename R, typename ... Args> struct function_traits; + template <typename R, typename ... Args> struct function_traits<std::function<R(Args...)>> { + template<int A> struct arg { + typedef typename std::tuple_element<A, std::tuple<Args...>>::type type; + }; + }; + template <typename F> struct callable_traits : public function_traits<std::function<typename std::remove_pointer<F>::type>> { }; + + // Converters that remove "optionalness". + template <typename X> + struct Coerce { + typedef typename std::remove_const<typename std::remove_reference<X>::type>::type T; + + T & operator()(T & x) const { return x; } + const T & operator()(const T & x) const { return x; } + template <typename Y> + T & operator()(IceUtil::Optional<Y> & x) const { if (!x) x = Y(); return *x; } + template <typename Y> + const T & operator()(const IceUtil::Optional<Y> & x) const { return *x; } + }; + template <typename X> + struct Coerce<IceUtil::Optional<X>> { + typedef typename std::remove_const<typename std::remove_reference<X>::type>::type T; + + IceUtil::Optional<T> & operator()(IceUtil::Optional<T> & x) const { return x; } + const IceUtil::Optional<T> & operator()(const IceUtil::Optional<T> & x) const { return x; } + template <typename Y> + IceUtil::Optional<T> operator()(Y & y) const { return y; } + }; + + // Value exists check + template <typename X, typename Y> + typename std::enable_if<std::is_constructible<X, Y>::value, bool>::type + valueExists(const Y &) { return true; } + template <typename X, typename Y> + typename std::enable_if<std::is_constructible<X, Y>::value, bool>::type + valueExists(const IceUtil::Optional<Y> & y) { return y; } + template<typename ET, typename MT, typename Conv> inline bool ModelPartForConvertedBase::tryConvertFrom(const ValueSourcePtr & vsp, MT * model, const Conv & conv) { if (auto vspt = dynamic_cast<TValueSource<ET> *>(vsp.get())) { + typedef typename callable_traits<Conv>::template arg<0>::type CA; ET tmp; vspt->set(tmp); - *model = conv(tmp); + auto converted = conv(Coerce<CA>()(tmp)); + if (valueExists<MT>(converted)) { + *model = Coerce<MT>()(converted); + } return true; } return false; @@ -187,7 +243,9 @@ namespace Slicer { bool ModelPartForConvertedBase::tryConvertFrom(const ValueSourcePtr & vsp, MT * model) { if (auto vspt = dynamic_cast<TValueSource<ET> *>(vsp.get())) { - vspt->set(*model); + if (valueExists<ET>(*model)) { + vspt->set(Coerce<ET>()(*model)); + } return true; } return false; @@ -195,10 +253,16 @@ namespace Slicer { template<typename ET, typename MT, typename Conv> inline - bool ModelPartForConvertedBase::tryConvertTo(const ValueTargetPtr & vsp, MT * model, const Conv & conv) + bool ModelPartForConvertedBase::tryConvertTo(const ValueTargetPtr & vsp, const MT * model, const Conv & conv) { if (auto vspt = dynamic_cast<TValueTarget<ET> *>(vsp.get())) { - vspt->get(conv(*model)); + typedef typename callable_traits<Conv>::template arg<0>::type CA; + if (valueExists<CA>(*model)) { + auto converted = conv(Coerce<CA>()(*model)); + if (valueExists<ET>(converted)) { + vspt->get(Coerce<ET>()(converted)); + } + } return true; } return false; @@ -206,10 +270,12 @@ namespace Slicer { template<typename ET, typename MT> inline - bool ModelPartForConvertedBase::tryConvertTo(const ValueTargetPtr & vsp, MT * model) + bool ModelPartForConvertedBase::tryConvertTo(const ValueTargetPtr & vsp, const MT * model) { if (auto vspt = dynamic_cast<TValueTarget<ET> *>(vsp.get())) { - vspt->get(*model); + if (valueExists<ET>(*model)) { + vspt->get(Coerce<ET>()(*model)); + } return true; } return false; diff --git a/slicer/tool/parser.cpp b/slicer/tool/parser.cpp index 4458661..de3f699 100644 --- a/slicer/tool/parser.cpp +++ b/slicer/tool/parser.cpp @@ -269,13 +269,7 @@ namespace Slicer { } fprintbf(cpp, " %s, ", Slice::typeToString(type, dm->optional())); - if (dm->optional()) { - fprintbf(cpp, "ModelPartForOptional< "); - } createNewModelPartPtrFor(type, dm, getAllMetadata(dm)); - if (dm->optional()) { - fprintbf(cpp, " > "); - } fprintbf(cpp, " >(&%s, \"%s\"", dm->scoped(), name ? *name : dm->name()); @@ -430,8 +424,7 @@ namespace Slicer { void Slicer::createModelPartForConverted(const Slice::TypePtr & type, const std::string & container, const Slice::DataMemberPtr & dm) const { - fprintbf(cpp, "ModelPartForConverted< %s, ", - Slice::typeToString(type)); + fprintbf(cpp, "ModelPartForConverted< "); if (dm->optional()) { fprintbf(cpp, "IceUtil::Optional< %s >", Slice::typeToString(type)); @@ -459,8 +452,14 @@ namespace Slicer { boost::algorithm::replace_all_copy(*cmp, ".", "::")); } else { + if (dm && dm->optional()) { + fprintbf(cpp, "ModelPartForOptional< "); + } fprintbf(cpp, "%s< %s >", getBasicModelPart(type), Slice::ClassDeclPtr::dynamicCast(type) ? type->typeId() : Slice::typeToString(type)); + if (dm && dm->optional()) { + fprintbf(cpp, " > "); + } } } |