/*=============================================================================
    Copyright (c) 2001-2011 Joel de Guzman
    Copyright (c) 2011 Eric Niebler

    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_FIND_05052005_1107)
#define FUSION_FIND_05052005_1107

#include <boost/fusion/support/config.hpp>
#include <boost/fusion/algorithm/query/find_if_fwd.hpp>
#include <boost/fusion/algorithm/query/detail/find_if.hpp>
#include <boost/fusion/algorithm/query/detail/segmented_find.hpp>
#include <boost/fusion/iterator/key_of.hpp>
#include <boost/fusion/iterator/value_of.hpp>
#include <boost/fusion/support/category_of.hpp>
#include <boost/fusion/support/is_segmented.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/utility/enable_if.hpp>

namespace boost {
namespace fusion {
namespace result_of {
template <typename Sequence, typename T>
struct find
    : mpl::if_<
      traits::is_segmented<Sequence>
    , detail::result_of_segmented_find<Sequence, T>
    , detail::result_of_find_if<
    Sequence,
    is_same<
    typename mpl::if_<
    traits::is_associative<Sequence>
    , key_of<mpl::_1>
    , value_of<mpl::_1>
    >::type
    , T
    >
    >
    >::type
{};
}

template <typename T, typename Sequence>
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
inline typename
lazy_disable_if<
is_const<Sequence>
, result_of::find<Sequence, T>
>::type const
find(Sequence& seq)
{
    typedef typename result_of::find<Sequence, T>::filter filter;
    return filter::call(seq);
}

template <typename T, typename Sequence>
BOOST_CONSTEXPR BOOST_FUSION_GPU_ENABLED
inline typename result_of::find<Sequence const, T>::type const
find(Sequence const& seq)
{
    typedef typename result_of::find<Sequence const, T>::filter filter;
    return filter::call(seq);
}
}
}

#endif
