
// Copyright (C) 2005-2011 Daniel James
// 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 BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED
#define BOOST_UNORDERED_DETAIL_EXTRACT_KEY_HPP_INCLUDED

#include <ndnboost/unordered/detail/table.hpp>

namespace ndnboost {
namespace unordered {
namespace detail {

    // key extractors
    //
    // no throw
    //
    // 'extract_key' is called with the emplace parameters to return a
    // key if available or 'no_key' is one isn't and will need to be
    // constructed. This could be done by overloading the emplace implementation
    // for the different cases, but that's a bit tricky on compilers without
    // variadic templates.

    struct no_key {
        no_key() {}
        template <class T> no_key(T const&) {}
    };

    template <typename Key, typename T>
    struct is_key {
        template <typename T2>
        static choice1::type test(T2 const&);
        static choice2::type test(Key const&);
        
        enum { value = sizeof(test(ndnboost::unordered::detail::make<T>())) ==
            sizeof(choice2::type) };
        
        typedef typename ndnboost::detail::if_true<value>::
            BOOST_NESTED_TEMPLATE then<Key const&, no_key>::type type;
    };

    template <class ValueType>
    struct set_extractor
    {
        typedef ValueType value_type;
        typedef ValueType key_type;

        static key_type const& extract(key_type const& v)
        {
            return v;
        }

        static no_key extract()
        {
            return no_key();
        }
        
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
        template <class... Args>
        static no_key extract(Args const&...)
        {
            return no_key();
        }
#else
        template <class Arg>
        static no_key extract(Arg const&)
        {
            return no_key();
        }

        template <class Arg1, class Arg2>
        static no_key extract(Arg1 const&, Arg2 const&)
        {
            return no_key();
        }
#endif
    };

    template <class Key, class ValueType>
    struct map_extractor
    {
        typedef ValueType value_type;
        typedef typename ndnboost::remove_const<Key>::type key_type;

        static key_type const& extract(value_type const& v)
        {
            return v.first;
        }
            
        template <class Second>
        static key_type const& extract(std::pair<key_type, Second> const& v)
        {
            return v.first;
        }

        template <class Second>
        static key_type const& extract(
            std::pair<key_type const, Second> const& v)
        {
            return v.first;
        }

        template <class Arg1>
        static key_type const& extract(key_type const& k, Arg1 const&)
        {
            return k;
        }

#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
        template <class... Args>
        static no_key extract(Args const&...)
        {
            return no_key();
        }
#else

        static no_key extract()
        {
            return no_key();
        }

        template <class Arg>
        static no_key extract(Arg const&)
        {
            return no_key();
        }

        template <class Arg, class Arg1>
        static no_key extract(Arg const&, Arg1 const&)
        {
            return no_key();
        }
#endif

#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)

#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_)                          \
        template <typename T2>                                              \
        static no_key extract(ndnboost::unordered::piecewise_construct_t,      \
                namespace_ tuple<> const&, T2 const&)                       \
        {                                                                   \
            return no_key();                                                \
        }                                                                   \
                                                                            \
        template <typename T, typename T2>                                  \
        static typename is_key<key_type, T>::type                           \
            extract(ndnboost::unordered::piecewise_construct_t,                \
                namespace_ tuple<T> const& k, T2 const&)                    \
        {                                                                   \
            return typename is_key<key_type, T>::type(                      \
                namespace_ get<0>(k));                                      \
        }

#else

#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_)                          \
        static no_key extract(ndnboost::unordered::piecewise_construct_t,      \
                namespace_ tuple<> const&)                                  \
        {                                                                   \
            return no_key();                                                \
        }                                                                   \
                                                                            \
        template <typename T>                                               \
        static typename is_key<key_type, T>::type                           \
            extract(ndnboost::unordered::piecewise_construct_t,                \
                namespace_ tuple<T> const& k)                               \
        {                                                                   \
            return typename is_key<key_type, T>::type(                      \
                namespace_ get<0>(k));                                      \
        }

#endif

BOOST_UNORDERED_KEY_FROM_TUPLE(ndnboost::)

#if !defined(BOOST_NO_CXX11_HDR_TUPLE)
BOOST_UNORDERED_KEY_FROM_TUPLE(std::)
#endif
    };
}}}

#endif
