summaryrefslogtreecommitdiffstats
path: root/src/FunctionRef.h
diff options
context:
space:
mode:
authorpeterbell10 <peterbell10@live.co.uk>2017-09-11 23:20:49 +0200
committerMattes D <github@xoft.cz>2017-09-11 23:20:49 +0200
commite225b7f8262df48ad4d7094bc295add3007b0649 (patch)
treea42e9afcc88cfe6e9d1258458e3ad42764083d0e /src/FunctionRef.h
parentcBlockArea: change MakeIndex to return size_t (diff)
downloadcuberite-e225b7f8262df48ad4d7094bc295add3007b0649.tar
cuberite-e225b7f8262df48ad4d7094bc295add3007b0649.tar.gz
cuberite-e225b7f8262df48ad4d7094bc295add3007b0649.tar.bz2
cuberite-e225b7f8262df48ad4d7094bc295add3007b0649.tar.lz
cuberite-e225b7f8262df48ad4d7094bc295add3007b0649.tar.xz
cuberite-e225b7f8262df48ad4d7094bc295add3007b0649.tar.zst
cuberite-e225b7f8262df48ad4d7094bc295add3007b0649.zip
Diffstat (limited to 'src/FunctionRef.h')
-rw-r--r--src/FunctionRef.h58
1 files changed, 58 insertions, 0 deletions
diff --git a/src/FunctionRef.h b/src/FunctionRef.h
new file mode 100644
index 000000000..8215fd0db
--- /dev/null
+++ b/src/FunctionRef.h
@@ -0,0 +1,58 @@
+
+#pragma once
+
+// Declared only so it can be partially specialized
+template <class Signature>
+class cFunctionRef;
+
+/** A light-weight, type-erased reference to a function object.
+This is similar to a std::function but doesn't copy the function object
+which means that mutable function objects will be modified for the caller
+but would not be if using a std::function (See #3990 for implications of this).
+A cFunctionRef has no empty state but is non-owning and so is safe to call
+as long as the referred object is still alive. */
+template <class Ret, class... Args>
+class cFunctionRef<Ret(Args...)>
+{
+public:
+ /** Construct from a function object. */
+ template <class FunctionObject>
+ cFunctionRef(FunctionObject && a_FunctionObject)
+ {
+ // Store an opaque reference to the object.
+ m_CallableData = &a_FunctionObject;
+
+ // Along with a function that knows how to call the object.
+ m_CallFunction = &ObjectFunctionCaller<FunctionObject>;
+ }
+
+ /** Call the referenced function object */
+ Ret operator () (Args... a_Args)
+ {
+ return m_CallFunction(m_CallableData, std::forward<Args>(a_Args)...);
+ }
+
+private:
+
+ /** Function that performs the call. */
+ template <class ObjectType>
+ static Ret ObjectFunctionCaller(void * a_Callable, Args... a_Args)
+ {
+ // Convert opaque reference to the concrete type.
+ using ObjectPtr = typename std::add_pointer<ObjectType>::type;
+ auto & Object = *static_cast<ObjectPtr>(a_Callable);
+
+ // Forward the call down to the object.
+ return Object(std::forward<Args>(a_Args)...);
+ }
+
+ using cCallFunction = Ret(*)(void *, Args...);
+
+ /** Type erased reference to a callable. */
+ void * m_CallableData;
+
+ /** Function that knows how to call the type erased reference. */
+ cCallFunction m_CallFunction;
+};
+
+