Jump to content

  • Log In with Google      Sign In   
  • Create Account

FREE SOFTWARE GIVEAWAY

We have 4 x Pro Licences (valued at $59 each) for 2d modular animation software Spriter to give away in this Thursday's GDNet Direct email newsletter.


Read more in this forum topic or make sure you're signed up (from the right-hand sidebar on the homepage) and read Thursday's newsletter to get in the running!


#Actualkloffy

Posted 14 March 2013 - 03:07 PM

Ok, so here is an alternative. The static member function check is still pretty ugly (a lot of code duplication). Luckily, the "client" never has to look at it.

template<typename Target, typename Source>
struct is_convertible_to
{
private:
	template<class U, class Enable = typename std::enable_if<!std::is_member_pointer<decltype(&U::to)>::value>::type>
	static std::true_type check(int);
	template<class U>
	static std::false_type check(...);

public:
	typedef decltype(check<conversion<Target, Source>>(0)) type;
	static const bool value = type::value;
};

template<typename Target, typename Source>
struct is_convertible_from
{
private:
	template<class U, class Enable = typename std::enable_if<!std::is_member_pointer<decltype(&U::from)>::value>::type>
	static std::true_type check(int);
	template<class U>
	static std::false_type check(...);

public:
	typedef decltype(check<conversion<Target, Source>>(0)) type;
	static const bool value = type::value;
};

 

Now, one can write the following functions:

template<typename Target, typename Source, typename Enable = void>
struct conversion
{
	//static Target to(Source const& value);
	//static Source from(Target const& value);
};

template<typename Target, typename Source>
typename std::enable_if<is_convertible_to<Target, Source>::value, Target>::type
conversion_cast(Source const& value)
{
	return conversion<Target, Source>::to(value);
}

template<typename Target, typename Source>
typename std::enable_if<!is_convertible_to<Target, Source>::value && is_convertible_from<Source, Target>::value, Target>::type
conversion_cast(Source const& value)
{
	return conversion<Source, Target>::from(value);
}

 

Finally, all this work is to allow the user to write conversions as specializations of the conversion template. Here is a trivial example:

template<>
struct conversion<int, float>
{
	static int to(float const& value)
	{
		return static_cast<int>(value);
	}

	static float from(int const& value)
	{
		return static_cast<float>(value);
	}
};

 

Which would be used as follows:

conversion_cast<int>(1.0f);
conversion_cast<float>(1);

 

So, the point of conversion_cast is to be extensible to arbitrary user defined types. The motivation was that I was integrating different libraries, which required conversions back and forth between types within those libraries. This seems like pretty basic stuff. Am I reinventing the wheel?


#2kloffy

Posted 14 March 2013 - 02:59 PM

Ok, so here is an alternative. The static member function check is still pretty ugly (a lot of code duplication). Luckily, the "client" never has to look at it.

template<typename Target, typename Source>
struct is_convertible_to
{
private:
	template<class U, class Enable = typename std::enable_if<!std::is_member_pointer<decltype(&U::to)>::value>::type>
	static std::true_type check(int);
	template<class U>
	static std::false_type check(...);

public:
	typedef decltype(check<conversion<Target, Source>>(0)) type;
	static const bool value = type::value;
};

template<typename Target, typename Source>
struct is_convertible_from
{
private:
	template<class U, class Enable = typename std::enable_if<!std::is_member_pointer<decltype(&U::from)>::value>::type>
	static std::true_type check(int);
	template<class U>
	static std::false_type check(...);

public:
	typedef decltype(check<conversion<Target, Source>>(0)) type;
	static const bool value = type::value;
};

 

Now, one can write the following functions:

template<typename Target, typename Source, typename Enable = void>
struct conversion
{
	//static Target to(Source const& value);
	//static Source from(Target const& value);
};

template<typename Target, typename Source>
typename std::enable_if<is_convertible_to<Target, Source>::value, Target>::type
conversion_cast(Source const& value)
{
	return conversion<Target, Source>::to(value);
}

template<typename Target, typename Source>
typename std::enable_if<!is_convertible_to<Target, Source>::value && is_convertible_from<Source, Target>::value, Target>::type
conversion_cast(Source const& value)
{
	return conversion<Source, Target>::from(value);
}

 

Finally, all this work is to allow the user to write conversions as specializations of the conversion template. Here is a trivial example:

template<>
struct conversion<int, float>
{
	static int to(float const& value)
	{
		return static_cast<int>(value);
	}

	static float from(int const& value)
	{
		return static_cast<float>(value);
	}
};

 

Which would be used as follows:

conversion_cast<int>(1.0f);
conversion_cast<float>(1);

 

So, the point of conversion_cast is to be extensible to arbitrary user defined types. The motivation was that I was integrating different libraries, which required conversions back and forth between types in those libraries. This seems like pretty basic stuff. Am I reinventing the wheel?


#1kloffy

Posted 14 March 2013 - 02:58 PM

Ok, so here is an alternative. The static member function check is still pretty ugly (a lot of code duplication). Luckily, the "client" never has to look at it.
template<typename Target, typename Source>
struct is_convertible_to
{
private:
	template<class U, class Enable = typename std::enable_if<!std::is_member_pointer<decltype(&U::to)>::value>::type>
	static std::true_type check(int);
	template<class U>
	static std::false_type check(...);

public:
	typedef decltype(check<conversion<Target, Source>>(0)) type;
	static const bool value = type::value;
};

template<typename Target, typename Source>
struct is_convertible_from
{
private:
	template<class U, class Enable = typename std::enable_if<!std::is_member_pointer<decltype(&U::from)>::value>::type>
	static std::true_type check(int);
	template<class U>
	static std::false_type check(...);

public:
	typedef decltype(check<conversion<Target, Source>>(0)) type;
	static const bool value = type::value;
};
Now, one can write the following functions:
template<typename Target, typename Source, typename Enable = void>
struct conversion
{
	//static Target to(Source const& value);
	//static Source from(Target const& value);
};

template<typename Target, typename Source>
typename std::enable_if<is_convertible_to<Target, Source>::value, Target>::type
conversion_cast(Source const& value)
{
	return conversion<Target, Source>::to(value);
}

template<typename Target, typename Source>
typename std::enable_if<!is_convertible_to<Target, Source>::value && is_convertible_from<Source, Target>::value, Target>::type
conversion_cast(Source const& value)
{
	return conversion<Source, Target>::from(value);
}
Finally, all this work is to allow the user to write conversions as specializations of the conversion template. Here is a trivial example:
template<>
struct conversion<int, float>
{
	static int to(float const& value)
	{
		return static_cast<int>(value);
	}

	static float from(int const& value)
	{
		return static_cast<float>(value);
	}
};
Which would be used as follows:
conversion_cast<int>(1.0f);
conversion_cast<float>(1);
So, the conversion_cast is extensible to arbitrary types. The motivation was that I was integrating different libraries, which required conversions back and forth between types in those libraries. This seems like pretty basic stuff. Am I reinventing the wheel?

PARTNERS