summaryrefslogtreecommitdiff
path: root/boost/poly_collection/detail/callable_wrapper.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/poly_collection/detail/callable_wrapper.hpp')
-rw-r--r--boost/poly_collection/detail/callable_wrapper.hpp104
1 files changed, 104 insertions, 0 deletions
diff --git a/boost/poly_collection/detail/callable_wrapper.hpp b/boost/poly_collection/detail/callable_wrapper.hpp
new file mode 100644
index 0000000000..9b339db8f2
--- /dev/null
+++ b/boost/poly_collection/detail/callable_wrapper.hpp
@@ -0,0 +1,104 @@
+/* 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 <boost/poly_collection/detail/is_invocable.hpp>
+#include <functional>
+#include <type_traits>
+#include <typeinfo>
+
+namespace boost{
+
+namespace poly_collection{
+
+namespace detail{
+
+/* lightweight std::function look-alike over non-owned callable entities */
+
+template<typename Signature>
+class callable_wrapper;
+
+template<typename R,typename... Args>
+class callable_wrapper<R(Args...)>
+{
+public:
+ // TODO: we should prevent assignment by user code
+ template<
+ typename Callable,
+ typename std::enable_if<
+ !std::is_same<Callable,callable_wrapper>::value&&
+ is_invocable_r<R,Callable,Args...>::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>(args)...);}
+
+ const std::type_info& target_type()const noexcept{return pt->info;}
+
+ template<typename T>
+ T* target()noexcept
+ {return typeid(T)==pt->info?static_cast<T*>(px):nullptr;}
+ template<typename T>
+ const T* target()const noexcept
+ {return typeid(T)==pt->info?static_cast<const T*>(px):nullptr;}
+
+ /* not in std::function interface */
+
+ operator std::function<R(Args...)>()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<R(Args...)> (*convert)(void*);
+ };
+
+ template<typename Callable>
+ static table* info(Callable&)noexcept
+ {
+ static table t={
+ [](void* p,Args... args){
+ auto r=std::ref(*static_cast<Callable*>(p));
+ return static_cast<R>(r(std::forward<Args>(args)...));
+ },
+ typeid(Callable),
+ [](void* p){
+ auto r=std::ref(*static_cast<Callable*>(p));
+ return std::function<R(Args...)>{r};
+ }
+ };
+ return &t;
+ }
+
+ table* pt;
+ void* px;
+};
+
+} /* namespace poly_collection::detail */
+
+} /* namespace poly_collection */
+
+} /* namespace boost */
+
+#endif