Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/poly_collection/detail/callable_wrapper.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /* Copyright 2016-2017 Joaquin M Lopez Munoz.
0002  * Distributed under the Boost Software License, Version 1.0.
0003  * (See accompanying file LICENSE_1_0.txt or copy at
0004  * http://www.boost.org/LICENSE_1_0.txt)
0005  *
0006  * See http://www.boost.org/libs/poly_collection for library home page.
0007  */
0008 
0009 #ifndef BOOST_POLY_COLLECTION_DETAIL_CALLABLE_WRAPPER_HPP
0010 #define BOOST_POLY_COLLECTION_DETAIL_CALLABLE_WRAPPER_HPP
0011 
0012 #if defined(_MSC_VER)
0013 #pragma once
0014 #endif
0015 
0016 #include <boost/poly_collection/detail/is_invocable.hpp>
0017 #include <functional>
0018 #include <type_traits>
0019 #include <typeinfo>
0020 
0021 namespace boost{
0022 
0023 namespace poly_collection{
0024 
0025 namespace detail{
0026 
0027 /* lightweight std::function look-alike over non-owned callable entities */
0028 
0029 template<typename Signature>
0030 class callable_wrapper;
0031 
0032 template<typename R,typename... Args>
0033 class callable_wrapper<R(Args...)>
0034 {
0035 public:
0036   // TODO: we should prevent assignment by user code
0037   template<
0038     typename Callable,
0039     typename std::enable_if<
0040       !std::is_same<Callable,callable_wrapper>::value&&
0041       is_invocable_r<R,Callable,Args...>::value
0042     >::type* =nullptr
0043   >
0044   explicit callable_wrapper(Callable& x)noexcept:pt{info(x)},px{&x}{}
0045   callable_wrapper(const callable_wrapper&)=default;
0046   callable_wrapper& operator=(const callable_wrapper&)=default;
0047 
0048   explicit operator bool()const noexcept{return true;}
0049 
0050   R operator()(Args... args)const
0051     {return pt->call(px,std::forward<Args>(args)...);}
0052 
0053   const std::type_info& target_type()const noexcept{return pt->info;}
0054 
0055   template<typename T>
0056   T*       target()noexcept
0057              {return typeid(T)==pt->info?static_cast<T*>(px):nullptr;}
0058   template<typename T>
0059   const T* target()const noexcept
0060              {return typeid(T)==pt->info?static_cast<const T*>(px):nullptr;}
0061 
0062   /* not in std::function interface */
0063 
0064   operator std::function<R(Args...)>()const noexcept{return pt->convert(px);}
0065 
0066   void*       data()noexcept{return px;}
0067   const void* data()const noexcept{return px;}
0068 
0069 private:
0070   struct table
0071   {
0072     R(*call)(void*,Args...);
0073     const std::type_info& info;
0074     std::function<R(Args...)> (*convert)(void*);
0075   };
0076 
0077   template<typename Callable>
0078   static table* info(Callable&)noexcept
0079   {
0080     static table t={
0081       [](void* p,Args... args){
0082         auto r=std::ref(*static_cast<Callable*>(p));
0083         return static_cast<R>(r(std::forward<Args>(args)...));
0084       },
0085       typeid(Callable),
0086       [](void* p){
0087         auto r=std::ref(*static_cast<Callable*>(p));
0088         return std::function<R(Args...)>{r};
0089       }
0090     };
0091     return &t;
0092   }
0093 
0094   table* pt;
0095   void*  px;
0096 };
0097 
0098 } /* namespace poly_collection::detail */
0099 
0100 } /* namespace poly_collection */
0101 
0102 } /* namespace boost */
0103 
0104 #endif