Maybeモナドみたいなものが作りたかった

メタプログラミング難しいし、モナド則にちゃんと則ってるかよくわかんないし。

メタプログラミング難しいし、モナド則にちゃんと則ってるかよくわかんないし。

  • タグ:
  • タグはありません
#include <cstdio>

#include <boost/optional.hpp>
#include <boost/type_traits.hpp>
#include <boost/utility/result_of.hpp>


template <typename T>
struct is_optional : public boost::false_type
{ };

template <typename T>
struct is_optional<boost::optional<T> > : public boost::true_type
{ };

template <typename T, typename F,
	typename Reserver = typename boost::disable_if<is_optional<typename boost::result_of<F(T)>::type>>::type,
	typename Reserver2 = typename boost::disable_if<boost::is_void<typename boost::result_of<F(T)>::type>>::type
>
inline boost::optional<typename boost::result_of<F(T)>::type> operator >> (boost::optional<T> val, F func)
{
	if (val) {
		return func(*val);
	} else {
		return boost::none;
	}
}

template <typename T, typename F, typename Reserver = typename boost::enable_if<is_optional<typename boost::result_of<F(T)>::type>>::type>
inline typename boost::result_of<F(T)>::type operator >> (boost::optional<T> val, F func)
{
	if (val) {
		return func(*val);
	} else {
		return boost::none;
	}
}

template <typename T, typename F, typename Reserver = typename boost::enable_if<boost::is_void<typename boost::result_of<F(T)>::type>>::type>
inline void operator >> (boost::optional<T> val, F func)
{
	if (val) {
		return func(*val);
	}
}

boost::optional<int> testFunc(int n) {
	return (n % 2 == 0)? n/2 : boost::optional<int>();
}

int testFunc2(int n) {
	return n / 2;
}

int main(int argc, const char * argv[])
{
	testFunc(32)
	>> [] (int r) { return testFunc(r); }
	>> [] (int r) { return testFunc2(r); }
	>> [] (int r) { std::printf("%d", r); }
	;
}