1 // Boost.Range library 2 // 3 // Copyright Neil Groves 2014. Use, modification and 4 // distribution is subject to the Boost Software License, Version 5 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at 6 // http://www.boost.org/LICENSE_1_0.txt) 7 // 8 // For more information, see http://www.boost.org/libs/range/ 9 // 10 #ifndef BOOST_RANGE_DETAIL_DEFAULT_CONSTRUCTIBLE_UNARY_FN_HPP_INCLUDED 11 #define BOOST_RANGE_DETAIL_DEFAULT_CONSTRUCTIBLE_UNARY_FN_HPP_INCLUDED 12 13 #include <boost/optional/optional.hpp> 14 #include <boost/mpl/if.hpp> 15 #include <boost/type_traits/has_trivial_constructor.hpp> 16 17 namespace boost 18 { 19 namespace range_detail 20 { 21 22 template<typename F, typename R> 23 class default_constructible_unary_fn_wrapper 24 { 25 public: 26 typedef R result_type; 27 default_constructible_unary_fn_wrapper()28 default_constructible_unary_fn_wrapper() 29 { 30 } default_constructible_unary_fn_wrapper(const F & source)31 default_constructible_unary_fn_wrapper(const F& source) 32 : m_impl(source) 33 { 34 } default_constructible_unary_fn_wrapper(const default_constructible_unary_fn_wrapper & source)35 default_constructible_unary_fn_wrapper(const default_constructible_unary_fn_wrapper& source) 36 : m_impl(source.m_impl) 37 { 38 } operator =(const default_constructible_unary_fn_wrapper & source)39 default_constructible_unary_fn_wrapper& operator=(const default_constructible_unary_fn_wrapper& source) 40 { 41 if (source.m_impl) 42 { 43 // Lambda are not copy/move assignable. 44 m_impl.emplace(*source.m_impl); 45 } 46 else 47 { 48 m_impl.reset(); 49 } 50 return *this; 51 } 52 template<typename Arg> operator ()(const Arg & arg) const53 R operator()(const Arg& arg) const 54 { 55 BOOST_ASSERT(m_impl); 56 return (*m_impl)(arg); 57 } 58 template<typename Arg> operator ()(Arg & arg) const59 R operator()(Arg& arg) const 60 { 61 BOOST_ASSERT(m_impl); 62 return (*m_impl)(arg); 63 } 64 private: 65 boost::optional<F> m_impl; 66 }; 67 68 template<typename F, typename R> 69 struct default_constructible_unary_fn_gen 70 { 71 typedef typename boost::mpl::if_< 72 boost::has_trivial_default_constructor<F>, 73 F, 74 default_constructible_unary_fn_wrapper<F,R> 75 >::type type; 76 }; 77 78 } // namespace range_detail 79 } // namespace boost 80 81 #endif // include guard 82