1/*============================================================================= 2 Copyright (c) 2012 Paul Fultz II 3 implicit.h 4 Distributed under the Boost Software License, Version 1.0. (See accompanying 5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6==============================================================================*/ 7 8#ifndef BOOST_HOF_GUARD_FUNCTION_IMPLICIT_H 9#define BOOST_HOF_GUARD_FUNCTION_IMPLICIT_H 10 11/// implicit 12/// ======== 13/// 14/// Description 15/// ----------- 16/// 17/// The `implicit` adaptor is a static function adaptor that uses the type 18/// that the return value can be converted to, in order to determine the type 19/// of the template parameter. In essence, it will deduce the type for the 20/// template parameter using the type of variable the result is assigned to. 21/// Since it is a static function adaptor, the function must be default 22/// constructible. 23/// 24/// Synopsis 25/// -------- 26/// 27/// template<template <class...> class F> 28/// class implicit<F>; 29/// 30/// Semantics 31/// --------- 32/// 33/// assert(T(implicit<F>()(xs...)) == F<T>()(xs...)); 34/// 35/// Requirements 36/// ------------ 37/// 38/// F must be a template class, that is a: 39/// 40/// * [ConstFunctionObject](ConstFunctionObject) 41/// * DefaultConstructible 42/// 43/// Example 44/// ------- 45/// 46/// #include <boost/hof.hpp> 47/// #include <cassert> 48/// using namespace boost::hof; 49/// 50/// template<class T> 51/// struct auto_caster 52/// { 53/// template<class U> 54/// T operator()(U x) 55/// { 56/// return T(x); 57/// } 58/// }; 59/// 60/// static constexpr implicit<auto_caster> auto_cast = {}; 61/// 62/// struct auto_caster_foo 63/// { 64/// int i; 65/// explicit auto_caster_foo(int i_) : i(i_) {} 66/// 67/// }; 68/// 69/// int main() { 70/// float f = 1.5; 71/// int i = auto_cast(f); 72/// auto_caster_foo x = auto_cast(1); 73/// assert(1 == i); 74/// assert(1 == x.i); 75/// } 76/// 77 78#include <boost/hof/pack.hpp> 79#include <boost/hof/detail/result_of.hpp> 80 81namespace boost { namespace hof { namespace detail { 82 83template<class F, class Pack, class X, class=void> 84struct is_implicit_callable 85: std::false_type 86{}; 87 88#if BOOST_HOF_NO_EXPRESSION_SFINAE 89template<class F, class Pack, class X> 90struct is_implicit_callable<F, Pack, X, typename std::enable_if< 91 std::is_convertible<typename result_of<Pack, id_<F>>::type, X>::value 92>::type> 93: std::true_type 94{}; 95#else 96template<class F, class Pack, class X> 97struct is_implicit_callable<F, Pack, X, typename std::enable_if< 98 std::is_convertible<decltype(std::declval<Pack>()(std::declval<F>())), X>::value 99>::type> 100: std::true_type 101{}; 102#endif 103 104} 105 106 107template<template <class...> class F> 108struct implicit 109{ 110 template<class Pack> 111 struct invoker 112 { 113 Pack p; 114 115 constexpr invoker(Pack pp) BOOST_HOF_NOEXCEPT_CONSTRUCTIBLE(Pack, Pack&&) 116 : p(boost::hof::move(pp)) 117 {} 118 119 template<class X, class=typename std::enable_if<detail::is_implicit_callable<F<X>, Pack, X>::value>::type> 120 constexpr operator X() const BOOST_HOF_NOEXCEPT(noexcept(p(F<X>()))) 121 { 122 return p(F<X>()); 123 } 124 125#if !(defined(__GNUC__) && !defined (__clang__) && __GNUC__ == 4 && __GNUC_MINOR__ < 7) 126 invoker (const invoker&) = delete; 127 invoker& operator= (const invoker&) = delete; 128 129 private: 130 friend struct implicit; 131 invoker (invoker&&) = default; 132#endif 133 }; 134 135 struct make_invoker 136 { 137 template<class Pack> 138 constexpr invoker<Pack> operator()(Pack p) const BOOST_HOF_NOEXCEPT(noexcept(invoker<Pack>(boost::hof::move(p)))) 139 { 140 return invoker<Pack>(boost::hof::move(p)); 141 } 142 143 }; 144 145 template<class... Ts> 146 constexpr auto operator()(Ts&&... xs) const 147 BOOST_HOF_RETURNS 148 ( 149 BOOST_HOF_RETURNS_CONSTRUCT(make_invoker)()(boost::hof::pack_basic(BOOST_HOF_FORWARD(Ts)(xs)...)) 150 ); 151}; 152 153}} // namespace boost::hof 154 155#endif 156