diff options
| -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, " > "); +			}  		}  	} | 
