Advertisement
illwieckz

netradiant clang issue #3 file 2

Apr 4th, 2020
647
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.57 KB | None | 0 0
  1. /*
  2.    Copyright (C) 2001-2006, William Joseph.
  3.    All Rights Reserved.
  4.  
  5.    This file is part of GtkRadiant.
  6.  
  7.    GtkRadiant is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 2 of the License, or
  10.    (at your option) any later version.
  11.  
  12.    GtkRadiant is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.  
  17.    You should have received a copy of the GNU General Public License
  18.    along with GtkRadiant; if not, write to the Free Software
  19.    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  20.  */
  21.  
  22. #if !defined( INCLUDED_GENERIC_CLOSURE_H )
  23. #define INCLUDED_GENERIC_CLOSURE_H
  24.  
  25. /// \file
  26. /// \brief Type-safe techniques for binding the first argument of an opaque callback.
  27.  
  28. #include <cstddef>
  29. #include "functional.h"
  30.  
  31. namespace detail {
  32.  
  33.     template<typename Thunk_>
  34.     class CallbackBase {
  35.         void *m_environment;
  36.         Thunk_ m_thunk;
  37.     public:
  38.         typedef Thunk_ Thunk;
  39.  
  40.         CallbackBase(void *environment, Thunk function) : m_environment(environment), m_thunk(function) {
  41.         }
  42.  
  43.         void *getEnvironment() const {
  44.             return m_environment;
  45.         }
  46.  
  47.         Thunk getThunk() const {
  48.             return m_thunk;
  49.         }
  50.     };
  51.  
  52.     template<typename Thunk>
  53.     inline bool operator==(const CallbackBase<Thunk> &self, const CallbackBase<Thunk> &other) {
  54.         return self.getEnvironment() == other.getEnvironment() && self.getThunk() == other.getThunk();
  55.     }
  56.  
  57.     template<typename Thunk>
  58.     inline bool operator!=(const CallbackBase<Thunk> &self, const CallbackBase<Thunk> &other) {
  59.         return !(self == other);
  60.     }
  61.  
  62.     template<typename Thunk>
  63.     inline bool operator<(const CallbackBase<Thunk> &self, const CallbackBase<Thunk> &other) {
  64.         return self.getEnvironment() < other.getEnvironment() ||
  65.                (!(other.getEnvironment() < self.getEnvironment()) && self.getThunk() < other.getThunk());
  66.     }
  67.  
  68. }
  69.  
  70. namespace detail {
  71.  
  72.     template<class Type>
  73.     struct ConvertFromOpaque {
  74.     };
  75.  
  76.     // reference
  77.  
  78.     template<class T>
  79.     inline const void *convertToOpaque(const T &t) {
  80.         return &t;
  81.     }
  82.  
  83.     template<class T>
  84.     struct ConvertFromOpaque<const T &> {
  85.         static T const &apply(void *p) {
  86.             return *static_cast<const T *>(p);
  87.         }
  88.     };
  89.  
  90.     template<class T>
  91.     inline void *convertToOpaque(T &t) {
  92.         return &t;
  93.     }
  94.  
  95.     template<class T>
  96.     struct ConvertFromOpaque<T &> {
  97.         static T &apply(void *p) {
  98.             return *static_cast<T *>( p );
  99.         }
  100.     };
  101.  
  102.     // pointer
  103.  
  104.     template<class T, class U = typename std::enable_if<!std::is_function<T>::value>::type>
  105.     inline const void *convertToOpaque(const T *t) {
  106.         return t;
  107.     }
  108.  
  109.     template<class T>
  110.     struct ConvertFromOpaque<const T *> {
  111.         static const T *apply(void *p) {
  112.             return static_cast<const T *>(p);
  113.         }
  114.     };
  115.  
  116.     template<class T, class U = typename std::enable_if<!std::is_function<T>::value>::type>
  117.     template<class T>
  118.     inline void *convertToOpaque(T *t) {
  119.         return t;
  120.     }
  121.  
  122.     template<class T>
  123.     struct ConvertFromOpaque<T *> {
  124.         static T *apply(void *p) {
  125.             return static_cast<T *>(p);
  126.         }
  127.     };
  128.  
  129.     // function pointer
  130.  
  131.     template<class R, class... Ts>
  132.     inline const void *convertToOpaque(R(*const &t)(Ts...)) {
  133.         return &t;
  134.     }
  135.  
  136.     template<class R, class... Ts>
  137.     struct ConvertFromOpaque<R(*const &)(Ts...)> {
  138.         using Type = R(*)(Ts...);
  139.  
  140.         static Type const &apply(void *p) {
  141.             return *static_cast<Type *>(p);
  142.         }
  143.     };
  144.  
  145.     template<class R, class... Ts>
  146.     inline void *convertToOpaque(R(*&t)(Ts...)) {
  147.         return &t;
  148.     }
  149.  
  150.     template<class R, class... Ts>
  151.     struct ConvertFromOpaque<R(*&)(Ts...)> {
  152.         using Type = R(*)(Ts...);
  153.  
  154.         static Type &apply(void *p) {
  155.             return *static_cast<Type *>(p);
  156.         }
  157.     };
  158.  
  159.     template<class Caller, class F>
  160.     class BindFirstOpaqueN;
  161.  
  162.     template<class Caller, class R, class FirstBound, class... Ts>
  163.     class BindFirstOpaqueN<Caller, R(FirstBound, Ts...)> {
  164.         FirstBound firstBound;
  165.     public:
  166.         explicit BindFirstOpaqueN(FirstBound firstBound) : firstBound(firstBound) {
  167.         }
  168.  
  169.         R operator()(Ts... args) const {
  170.             return Caller::call(firstBound, args...);
  171.         }
  172.  
  173.         FirstBound getBound() const {
  174.             return firstBound;
  175.         }
  176.  
  177.         static R thunk(void *environment, Ts... args) {
  178.             return thunk_(detail::ConvertFromOpaque<FirstBound>::apply(environment), args...);
  179.         }
  180.  
  181.         static R thunk_(FirstBound environment, Ts... args) {
  182.             return Caller::call(environment, args...);
  183.         }
  184.  
  185.         void *getEnvironment() const {
  186.             return const_cast<void *>(detail::convertToOpaque(firstBound));
  187.         }
  188.     };
  189.  
  190. }
  191.  
  192. template<class Caller>
  193. using BindFirstOpaque = detail::BindFirstOpaqueN<Caller, get_func<Caller>>;
  194.  
  195. /// \brief Combines a void pointer with a pointer to a function which operates on a void pointer.
  196. ///
  197. /// Use with the callback constructors MemberCaller0, ConstMemberCaller0, ReferenceCaller0, ConstReferenceCaller0, PointerCaller0, ConstPointerCaller0 and FreeCaller0.
  198. template<class F>
  199. class Callback;
  200.  
  201. template<class R, class... Ts>
  202. class Callback<R(Ts...)> : public detail::CallbackBase<R(*)(void *, Ts...)> {
  203.     using Base = detail::CallbackBase<R (*)(void *, Ts...)>;
  204.  
  205.     static R nullThunk(void *, Ts...) {
  206.     }
  207.  
  208. public:
  209.     using func = R(Ts...);
  210.  
  211.     Callback() : Base(0, nullThunk) {
  212.     }
  213.  
  214.     template<typename Caller>
  215.     Callback(const BindFirstOpaque<Caller> &caller) : Base(caller.getEnvironment(), BindFirstOpaque<Caller>::thunk) {
  216.     }
  217.  
  218.     Callback(void *environment, typename Base::Thunk function) : Base(environment, function) {
  219.     }
  220.  
  221.     R operator()(Ts... args) const {
  222.         return Base::getThunk()(Base::getEnvironment(), args...);
  223.     }
  224. };
  225.  
  226. namespace detail {
  227.     template<class F>
  228.     struct Arglist;
  229.  
  230.     template<class R, class Head, class... Ts>
  231.     struct Arglist<R(Head, Ts...)> {
  232.         using type = R(Head, Ts...);
  233.  
  234.         template <class Unshift>
  235.         using unshift = Arglist<R(Unshift, Head, Ts...)>;
  236.  
  237.         using shift = Arglist<R(Ts...)>;
  238.     };
  239.  
  240.     template<class R, class... Ts>
  241.     struct Arglist<R(Ts...)> {
  242.         using type = R(Ts...);
  243.  
  244.         template <class Unshift>
  245.         using unshift = Arglist<R(Unshift, Ts...)>;
  246.     };
  247.  
  248.     template<class F>
  249.     using ArgShift = typename detail::Arglist<F>::shift::type;
  250.  
  251.     template<class F, class T>
  252.     using ArgUnshift = typename detail::Arglist<F>::template unshift<T>::type;
  253. }
  254.  
  255. template<typename Caller>
  256. inline Callback<detail::ArgShift<get_func<Caller>>> makeCallback(const Caller &caller, get_argument<Caller, 0> callee) {
  257.     return BindFirstOpaque<Caller>(callee);
  258. }
  259.  
  260. template<class Caller, class F>
  261. class CallerShiftFirst;
  262.  
  263. template<class Caller, class R, class FirstArgument, class... Ts>
  264. class CallerShiftFirst<Caller, R(FirstArgument, Ts...)> {
  265. public:
  266.     using func = R(FirstArgument, Ts...);
  267.  
  268.     static R call(FirstArgument, Ts... args) {
  269.         return Caller::call(args...);
  270.     }
  271. };
  272.  
  273. template<typename Caller>
  274. inline Callback<get_func<Caller>> makeStatelessCallback(const Caller &caller) {
  275.     return makeCallback(CallerShiftFirst<Caller, detail::ArgUnshift<get_func<Caller>, void *>>(), nullptr);
  276. }
  277.  
  278. /// \brief Forms a Callback from a non-const Environment reference and a non-const Environment member-function.
  279. template<class Environment, class F, MemberFunction<Environment, F> member>
  280. using MemberCaller = BindFirstOpaque<Member<Environment, F, member>>;
  281.  
  282. /// \brief  Constructs a Callback1 from a non-const \p functor
  283. ///
  284. /// \param Functor Must define \c first_argument_type and \c operator()(first_argument_type).
  285. template<typename Functor>
  286. inline Callback<get_func<Functor>> makeCallback(Functor &functor) {
  287.     return MemberCaller<Functor, get_func<Functor>, &Functor::operator()>(functor);
  288. }
  289.  
  290. /// \brief Forms a Callback from a const Environment reference and a const Environment member-function.
  291. template<class Environment, class F, ConstMemberFunction<Environment, F> member>
  292. using ConstMemberCaller = BindFirstOpaque<ConstMember<Environment, F, member>>;
  293.  
  294. /// \brief  Constructs a Callback1 from a const \p functor
  295. ///
  296. /// \param Functor Must define \c first_argument_type and const \c operator()(first_argument_type).
  297. template<typename Functor>
  298. inline Callback<get_func<Functor>> makeCallback(const Functor &functor) {
  299.     return ConstMemberCaller<Functor, get_func<Functor>, &Functor::operator()>(functor);
  300. }
  301.  
  302. /// \brief Forms a Callback from a non-const Environment reference and a free function which operates on a non-const Environment reference.
  303. template<class Environment, class F, detail::ArgUnshift<F, Environment &> *func>
  304. using ReferenceCaller = BindFirstOpaque<Function<detail::ArgUnshift<F, Environment &>, func>>;
  305.  
  306. /// \brief Forms a Callback from a const Environment reference and a free function which operates on a const Environment reference.
  307. template<class Environment, class F, detail::ArgUnshift<F, const Environment &> *func>
  308. using ConstReferenceCaller = BindFirstOpaque<Function<detail::ArgUnshift<F, const Environment &>, func>>;
  309.  
  310. /// \brief Forms a Callback from a non-const Environment pointer and a free function which operates on a non-const Environment pointer.
  311. template<class Environment, class F, detail::ArgUnshift<F, Environment *> *func>
  312. using PointerCaller = BindFirstOpaque<Function<detail::ArgUnshift<F, Environment *>, func>>;
  313.  
  314. /// \brief Forms a Callback from a const Environment pointer and a free function which operates on a const Environment pointer.
  315. template<class Environment, class F, detail::ArgUnshift<F, const Environment *> *func>
  316. using ConstPointerCaller = BindFirstOpaque<Function<detail::ArgUnshift<F, const Environment *>, func>>;
  317.  
  318. namespace detail {
  319.     template<class Caller, class F>
  320.     class FreeCaller : public BindFirstOpaque<CallerShiftFirst<Caller, detail::ArgUnshift<F, void *>>> {
  321.     public:
  322.         FreeCaller() : BindFirstOpaque<CallerShiftFirst<Caller, detail::ArgUnshift<F, void *>>>(nullptr) {
  323.         }
  324.     };
  325.  
  326.     template<class F>
  327.     struct FreeCallerWrapper;
  328.  
  329.     template<class R, class... Ts>
  330.     struct FreeCallerWrapper<R(Ts...)> {
  331.         using func = R(void *, Ts...);
  332.  
  333.         static R call(void *f, Ts... args) {
  334.             // ideally, we'd get the implementation of the function type directly. Instead, it's passed in
  335.             return reinterpret_cast<R(*)(Ts...)>(f)(args...);
  336.         }
  337.     };
  338. }
  339.  
  340. /// \brief Forms a Callback from a free function
  341. template<class F, F *func>
  342. using FreeCaller = detail::FreeCaller<Function<F, func>, F>;
  343.  
  344. template<class R, class... Ts>
  345. inline Callback<R(Ts...)> makeCallbackF(R(*func)(Ts...)) {
  346.     void *pVoid = reinterpret_cast<void *>(func);
  347.     return BindFirstOpaque<detail::FreeCallerWrapper<R(Ts...)>>(pVoid);
  348. }
  349.  
  350. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement