From d17f90c71d4c8703c52c1ea1be383577d7771621 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Fri, 8 Sep 2017 19:29:04 +0100 Subject: Converted Model part now handles optionality internally (cases where it do so quirkily probably still exist) --- slicer/slicer/modelPartsTypes.h | 18 ++++++-- slicer/slicer/modelPartsTypes.impl.h | 82 ++++++++++++++++++++++++++++++++---- 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 inline static bool tryConvertFrom(const ValueSourcePtr & vsp, MT * model); template - 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 - inline static bool tryConvertTo(const ValueTargetPtr & vsp, MT * model); + inline static bool tryConvertTo(const ValueTargetPtr & vsp, const MT * model); }; - template + template class DLL_PUBLIC ModelPartForConverted : public ModelPartForConvertedBase, protected ModelPartModel { public: typedef T element_type; @@ -78,6 +78,18 @@ namespace Slicer { virtual void GetValue(ValueTargetPtr s) override; }; + template M::* MV> + class DLL_PUBLIC ModelPartForConverted, M, MV> : public ModelPartForConvertedBase, protected ModelPartModel> { + public: + typedef IceUtil::Optional element_type; + + ModelPartForConverted(IceUtil::Optional * 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 - ModelPartForConverted::ModelPartForConverted(T * h) : + template + ModelPartForConverted::ModelPartForConverted(T * h) : ModelPartModel(h) { } + template M::* MV> + ModelPartForConverted, M, MV>::ModelPartForConverted(IceUtil::Optional * h) : + ModelPartModel>(h) + { + } + + template M::* MV> + bool ModelPartForConverted, M, MV>::HasValue() const + { + BOOST_ASSERT(this->Model); + return *this->Model; + } + + // Function traits helpers + template struct function_traits; + template struct function_traits> { + template struct arg { + typedef typename std::tuple_element>::type type; + }; + }; + template struct callable_traits : public function_traits::type>> { }; + + // Converters that remove "optionalness". + template + struct Coerce { + typedef typename std::remove_const::type>::type T; + + T & operator()(T & x) const { return x; } + const T & operator()(const T & x) const { return x; } + template + T & operator()(IceUtil::Optional & x) const { if (!x) x = Y(); return *x; } + template + const T & operator()(const IceUtil::Optional & x) const { return *x; } + }; + template + struct Coerce> { + typedef typename std::remove_const::type>::type T; + + IceUtil::Optional & operator()(IceUtil::Optional & x) const { return x; } + const IceUtil::Optional & operator()(const IceUtil::Optional & x) const { return x; } + template + IceUtil::Optional operator()(Y & y) const { return y; } + }; + + // Value exists check + template + typename std::enable_if::value, bool>::type + valueExists(const Y &) { return true; } + template + typename std::enable_if::value, bool>::type + valueExists(const IceUtil::Optional & y) { return y; } + template inline bool ModelPartForConvertedBase::tryConvertFrom(const ValueSourcePtr & vsp, MT * model, const Conv & conv) { if (auto vspt = dynamic_cast *>(vsp.get())) { + typedef typename callable_traits::template arg<0>::type CA; ET tmp; vspt->set(tmp); - *model = conv(tmp); + auto converted = conv(Coerce()(tmp)); + if (valueExists(converted)) { + *model = Coerce()(converted); + } return true; } return false; @@ -187,7 +243,9 @@ namespace Slicer { bool ModelPartForConvertedBase::tryConvertFrom(const ValueSourcePtr & vsp, MT * model) { if (auto vspt = dynamic_cast *>(vsp.get())) { - vspt->set(*model); + if (valueExists(*model)) { + vspt->set(Coerce()(*model)); + } return true; } return false; @@ -195,10 +253,16 @@ namespace Slicer { template 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 *>(vsp.get())) { - vspt->get(conv(*model)); + typedef typename callable_traits::template arg<0>::type CA; + if (valueExists(*model)) { + auto converted = conv(Coerce()(*model)); + if (valueExists(converted)) { + vspt->get(Coerce()(converted)); + } + } return true; } return false; @@ -206,10 +270,12 @@ namespace Slicer { template inline - bool ModelPartForConvertedBase::tryConvertTo(const ValueTargetPtr & vsp, MT * model) + bool ModelPartForConvertedBase::tryConvertTo(const ValueTargetPtr & vsp, const MT * model) { if (auto vspt = dynamic_cast *>(vsp.get())) { - vspt->get(*model); + if (valueExists(*model)) { + vspt->get(Coerce()(*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, " > "); + } } } -- cgit v1.2.3