/*=============================================================================

    Copyright (c) 2001-2006 Joel de Guzman



    Distributed under the Boost Software License, Version 1.0. (See accompanying 

    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

==============================================================================*/

#if !defined(FUSION_COUNT_09162005_0158)

#define FUSION_COUNT_09162005_0158



#include <boost/mpl/or.hpp>

#include <boost/type_traits/is_convertible.hpp>

#include <boost/fusion/support/detail/access.hpp>



namespace boost { namespace fusion { namespace detail

{ 

    template <bool is_convertible>

    struct compare_convertible;



    // T1 is convertible to T2 or vice versa

    template <>

    struct compare_convertible<true> 

    {

        template <typename T1, typename T2>

        static bool

        call(T1 const& x, T2 const& y)

        {

            return x == y;

        }

    };



    // T1 is NOT convertible to T2 NOR vice versa

    template <>

    struct compare_convertible<false>

    {

        template <typename T1, typename T2>

        static bool

        call(T1 const&, T2 const&)

        {

            return false;

        }

    };



    template <typename T1>

    struct count_compare

    {

        typedef typename detail::call_param<T1>::type param;

        count_compare(param x)

            : x(x) {}



        template <typename T2>

        bool

        operator()(T2 const& y)

        {

            return 

                compare_convertible<

                    mpl::or_<

                        is_convertible<T1, T2>

                      , is_convertible<T2, T1> 

                    >::value

                >::call(x, y);

        }



        param x;

    };

}}}



#endif



