-// Copyright Daniel Wallin 2006. Use, modification and distribution is
-// subject to 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)
+// Copyright Daniel Wallin 2006.
+// Copyright Cromwell D. Enage 2017.
+// 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_PARAMETER_TEMPLATE_KEYWORD_060203_HPP
-# define BOOST_PARAMETER_TEMPLATE_KEYWORD_060203_HPP
+#define BOOST_PARAMETER_TEMPLATE_KEYWORD_060203_HPP
-# include <boost/mpl/and.hpp>
-# include <boost/mpl/not.hpp>
-# include <boost/type_traits/is_convertible.hpp>
-# include <boost/type_traits/is_reference.hpp>
+namespace boost { namespace parameter { namespace aux {
-namespace boost { namespace parameter {
+ struct template_keyword_base
+ {
+ };
+}}} // namespace boost::parameter::aux
-namespace aux
-{
+#include <boost/parameter/config.hpp>
- struct template_keyword_tag {};
+#if defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <type_traits>
- template <class T, class U>
- struct is_pointer_convertible
- : is_convertible<T*, U*>
- {};
+namespace boost { namespace parameter { namespace aux {
- template <class T>
- struct is_template_keyword
- : mpl::and_<
- mpl::not_<is_reference<T> >
- , is_pointer_convertible<T, template_keyword_tag>
- >
- {};
+ template <typename T>
+ using is_template_keyword = ::std::is_base_of<
+ ::boost::parameter::aux::template_keyword_base
+ , typename ::std::remove_const<
+ typename ::std::remove_reference<T>::type
+ >::type
+ >;
+}}} // namespace boost::parameter::aux
-} // namespace aux
+#else // !defined(BOOST_PARAMETER_CAN_USE_MP11)
+#include <boost/mpl/bool.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits/remove_const.hpp>
-template <class Tag, class T>
-struct template_keyword
- : aux::template_keyword_tag
-{
- typedef Tag key_type;
- typedef T value_type;
- typedef value_type reference;
-};
+#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#else
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/type_traits/is_lvalue_reference.hpp>
+#endif
-}} // namespace boost::parameter
+namespace boost { namespace parameter { namespace aux {
-#endif // BOOST_PARAMETER_TEMPLATE_KEYWORD_060203_HPP
+#if !defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+ template <typename T>
+ struct is_template_keyword_aux
+ : ::boost::mpl::if_<
+ ::boost::is_convertible<
+ T*
+ , ::boost::parameter::aux::template_keyword_base const*
+ >
+ , ::boost::mpl::true_
+ , ::boost::mpl::false_
+ >::type
+ {
+ };
+#endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING
+
+ template <typename T>
+ struct is_template_keyword
+ : ::boost::mpl::if_<
+#if defined(BOOST_PARAMETER_HAS_PERFECT_FORWARDING)
+ // Cannot use is_convertible<> to check if T is derived from
+ // template_keyword_base. -- Cromwell D. Enage
+ ::boost::is_base_of<
+ ::boost::parameter::aux::template_keyword_base
+ , typename ::boost::remove_const<
+ typename ::boost::remove_reference<T>::type
+ >::type
+ >
+ , ::boost::mpl::true_
+ , ::boost::mpl::false_
+#else
+ ::boost::is_lvalue_reference<T>
+ , ::boost::mpl::false_
+ , ::boost::parameter::aux::is_template_keyword_aux<T>
+#endif // BOOST_PARAMETER_HAS_PERFECT_FORWARDING
+ >::type
+ {
+ };
+}}} // namespace boost::parameter::aux
+
+#endif // BOOST_PARAMETER_CAN_USE_MP11
+#endif // include guard