Blob Blame Raw
#pragma once

#ifndef TCG_FUNCTIONAL_H
#define TCG_FUNCTIONAL_H

#include "traits.h"

// std includes
#include <functional>

//**********************************************************************************
//    Logical functor combinators
//**********************************************************************************

namespace tcg
{

template <typename Fn1, typename Fn2>
class unary_and : public std::unary_function<typename function_traits<Fn1>::arg_type, bool>
{
	Fn1 m_fn1;
	Fn2 m_fn2;

public:
	unary_and(const Fn1 &fn1, const Fn2 &fn2)
		: m_fn1(fn1), m_fn2(fn2) {}

	bool operator()(const typename function_traits<Fn1>::arg_type &t) const
	{
		return m_fn1(t) && m_fn2(t);
	}
};

template <typename Fn1, typename Fn2>
unary_and<Fn1, Fn2> and1(const Fn1 &fn1, const Fn2 &fn2)
{
	return unary_and<Fn1, Fn2>(fn1, fn2);
}

//----------------------------------------------------------------------------------

template <typename Fn1, typename Fn2>
class unary_or : public std::unary_function<typename function_traits<Fn1>::arg_type, bool>
{
	Fn1 m_fn1;
	Fn2 m_fn2;

public:
	unary_or(const Fn1 &fn1, const Fn2 &fn2)
		: m_fn1(fn1), m_fn2(fn2) {}

	bool operator()(const typename function_traits<Fn1>::arg_type &t) const
	{
		return m_fn1(t) || m_fn2(t);
	}
};

template <typename Fn1, typename Fn2>
unary_or<Fn1, Fn2> or1(const Fn1 &fn1, const Fn2 &fn2)
{
	return unary_or<Fn1, Fn2>(fn1, fn2);
}

} // namespace tcg

#endif // TCG_FUNCTIONAL_H