summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2017-09-08 19:29:04 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2017-09-10 22:20:42 +0100
commitd17f90c71d4c8703c52c1ea1be383577d7771621 (patch)
tree74920ee495c4914481c7b8c5850b057034f2a7f4
parentDon't use ClassType in the optionals test as it has a custom model type which... (diff)
downloadslicer-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.h18
-rw-r--r--slicer/slicer/modelPartsTypes.impl.h82
-rw-r--r--slicer/tool/parser.cpp15
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, " > ");
+ }
}
}