/* Copyright 2016-2017 Joaquin M Lopez Munoz. * 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) * * See http://www.boost.org/libs/poly_collection for library home page. */ #ifndef BOOST_POLY_COLLECTION_DETAIL_CALLABLE_WRAPPER_HPP #define BOOST_POLY_COLLECTION_DETAIL_CALLABLE_WRAPPER_HPP #if defined(_MSC_VER) #pragma once #endif #include #include #include #include namespace boost{ namespace poly_collection{ namespace detail{ /* lightweight std::function look-alike over non-owned callable entities */ template class callable_wrapper; template class callable_wrapper { public: // TODO: we should prevent assignment by user code template< typename Callable, typename std::enable_if< !std::is_same::value&& is_invocable_r::value >::type* =nullptr > explicit callable_wrapper(Callable& x)noexcept:pt{info(x)},px{&x}{} callable_wrapper(const callable_wrapper&)=default; callable_wrapper& operator=(const callable_wrapper&)=default; explicit operator bool()const noexcept{return true;} R operator()(Args... args)const {return pt->call(px,std::forward(args)...);} const std::type_info& target_type()const noexcept{return pt->info;} template T* target()noexcept {return typeid(T)==pt->info?static_cast(px):nullptr;} template const T* target()const noexcept {return typeid(T)==pt->info?static_cast(px):nullptr;} /* not in std::function interface */ operator std::function()const noexcept{return pt->convert(px);} void* data()noexcept{return px;} const void* data()const noexcept{return px;} private: struct table { R(*call)(void*,Args...); const std::type_info& info; std::function (*convert)(void*); }; template static table* info(Callable&)noexcept { static table t={ [](void* p,Args... args){ auto r=std::ref(*static_cast(p)); return static_cast(r(std::forward(args)...)); }, typeid(Callable), [](void* p){ auto r=std::ref(*static_cast(p)); return std::function{r}; } }; return &t; } table* pt; void* px; }; } /* namespace poly_collection::detail */ } /* namespace poly_collection */ } /* namespace boost */ #endif