// http://turtle.sourceforge.net
//
// Copyright Mathieu Champlon 2012
//
// 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)

#ifndef MOCK_SIGNATURE_HPP_INCLUDED
#define MOCK_SIGNATURE_HPP_INCLUDED

#include "../config.hpp"
#include <boost/function_types/parameter_types.hpp>
#include <boost/function_types/function_type.hpp>
#include <boost/function_types/result_type.hpp>
#include <boost/mpl/single_view.hpp>
#include <boost/mpl/joint_view.hpp>
#include <boost/mpl/pop_front.hpp>
#define BOOST_TYPEOF_SILENT
#include <boost/typeof/typeof.hpp>

namespace mock
{
namespace detail
{
    template< typename M >
    struct signature :
        boost::function_types::function_type<
            boost::mpl::joint_view<
                boost::mpl::single_view<
                    typename
                        boost::function_types::result_type< M >::type
                >,
                typename boost::mpl::pop_front<
                    typename
                        boost::function_types::parameter_types< M >
                >::type
            >
        >
    {};

    template< typename T >
    struct base
    {
        typedef T base_type;
    };

    // if an error is generated by the line below it means
    // the method is ambiguous : specify its signature to
    // disambiguate
    template< typename T >
    T& ambiguous_method_requires_to_specify_signature( const T& );
}
} // mock

#define MOCK_SIGNATURE(M) \
    mock::detail::signature< \
        BOOST_TYPEOF( \
            mock::detail::ambiguous_method_requires_to_specify_signature( \
                &base_type::M ) ) \
    >::type

#endif // MOCK_SIGNATURE_HPP_INCLUDED
