Callable.hpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. ///
  2. /// \file Callable/Callable.hpp
  3. ///
  4. /// Callable provides an opaque proxy for function or method calls.
  5. ///
  6. /// \copyright
  7. /// Copyright (c) 2013-2019 Josh Blum
  8. /// 2019 Nicholas Corgan
  9. /// SPDX-License-Identifier: BSL-1.0
  10. ///
  11. #pragma once
  12. #include <Pothos/Config.hpp>
  13. #include <Pothos/Callable/CallInterface.hpp>
  14. #include <Pothos/Object/Object.hpp>
  15. #include <vector>
  16. #include <memory>
  17. namespace Pothos {
  18. //messy forward declares
  19. namespace Detail {
  20. struct CallableContainer;
  21. } //namespace Detail
  22. /*!
  23. * The Callable class binds a class method or function.
  24. * The method/function can be called through an opaque Object interface,
  25. * or through a templated call interface with an arbitrary number of args.
  26. */
  27. class POTHOS_API Callable : public CallInterface
  28. {
  29. public:
  30. /*!
  31. * Create a null Callable.
  32. * Calling a null instance will throw CallableNullError.
  33. */
  34. Callable(void);
  35. /*!
  36. * Does the Callable hold a bound function?
  37. * \return true if callable holds a bound function
  38. */
  39. explicit operator bool(void) const;
  40. /*!
  41. * Call into the function/method with opaque input and return types.
  42. * For a void return type of call, the returned Object will be null.
  43. * \throws CallableNullError if the Callable is null
  44. * \throws CallableArgumentError for bad arguments in number or type
  45. * \param inputArgs an array of call arguments of type Object
  46. * \param numArgs the number of arguments in inputArgs
  47. * \return the return value of the call as type Object
  48. */
  49. Object opaqueCall(const Object *inputArgs, const size_t numArgs) const;
  50. /*!
  51. * Get the number of arguments for this call.
  52. * For methods, the class instance also counts
  53. * \return the number of arguments
  54. */
  55. size_t getNumArgs(void) const;
  56. /*!
  57. * Get the type info for a particular argument.
  58. * For the return type, use argNo = -1.
  59. * For argument 0 use argNo = 0, etc.
  60. * For methods, argNo = 0 is the class type.
  61. * \throws CallableArgumentError if the argNo is invalid
  62. * \return the type info for the argument
  63. */
  64. const std::type_info &type(const int argNo) const;
  65. /*!
  66. * Bind an argument to the given argument index - template version.
  67. * The user will not specify this argument at call time,
  68. * the bound argument will be used as a substitute.
  69. * The bind call does not throw.
  70. * \param val the value to put into the argument list
  71. * \param argNo the argument index to bind to
  72. * \return this Callable for operator chaining
  73. */
  74. template <typename ValueType>
  75. Callable &bind(ValueType &&val, const size_t argNo);
  76. /*!
  77. * Bind an argument to the given argument index - Object version.
  78. * The user will not specify this argument at call time,
  79. * the bound argument will be used as a substitute.
  80. * The bind call does not throw.
  81. * \param val the value to put into the argument list
  82. * \param argNo the argument index to bind to
  83. * \return this Callable for operator chaining
  84. */
  85. Callable &bind(Object &&val, const size_t argNo);
  86. /*!
  87. * Remove a binding at the given argument index.
  88. * The unbind call does not throw.
  89. * \param argNo the argument index to clear
  90. * \return this Callable for operator chaining
  91. */
  92. Callable &unbind(const size_t argNo);
  93. /*!
  94. * Get a string representation for this Callable.
  95. * The string holds the return type, and argument types.
  96. * \return the string with type names
  97. */
  98. std::string toString(void) const;
  99. //! Create a Callable for a class method with variable args
  100. template <typename ReturnType, typename ClassType, typename... ArgsType>
  101. Callable(ReturnType(ClassType::*fcn)(ArgsType...));
  102. //! Create a Callable for a const class method with variable args
  103. template <typename ReturnType, typename ClassType, typename... ArgsType>
  104. Callable(ReturnType(ClassType::*fcn)(ArgsType...) const);
  105. //! Create a Callable for a function with variable args
  106. template <typename ReturnType, typename... ArgsType>
  107. Callable(ReturnType(*fcn)(ArgsType...));
  108. //! Create a Callable for a std::function with variable args
  109. template <typename ReturnType, typename... ArgsType>
  110. Callable(const std::function<ReturnType(ArgsType...)> &fcn);
  111. /*!
  112. * Create a Callable for a class method with variable args.
  113. * Use make to specify explicit template arguments
  114. * to differentiate overloads with the same name.
  115. * In this case, the entire pack must be specified.
  116. */
  117. template <typename ReturnType, typename ClassType, typename... ArgsType>
  118. static Callable make(ReturnType(ClassType::*fcn)(ArgsType...));
  119. /*!
  120. * Create a Callable for a const class method with variable args.
  121. * Use make to specify explicit template arguments
  122. * to differentiate overloads with the same name.
  123. * In this case, the entire pack must be specified.
  124. */
  125. template <typename ReturnType, typename ClassType, typename... ArgsType>
  126. static Callable make(ReturnType(ClassType::*fcn)(ArgsType...) const);
  127. /*!
  128. * Create a Callable for a function with variable args.
  129. * Use make to specify explicit template arguments
  130. * to differentiate overloads with the same name.
  131. * In this case, the entire pack must be specified.
  132. */
  133. template <typename ReturnType, typename... ArgsType>
  134. static Callable make(ReturnType(*fcn)(ArgsType...));
  135. /*!
  136. * Create a Callable for a std::function with variable args
  137. * Use make to specify explicit template arguments
  138. * to differentiate overloads with the same name.
  139. * In this case, the entire pack must be specified.
  140. */
  141. template <typename ReturnType, typename... ArgsType>
  142. static Callable make(const std::function<ReturnType(ArgsType...)> &fcn);
  143. /*!
  144. * Create a Callable for a constructor with variable args.
  145. * Template arguments must be explicitly specified.
  146. */
  147. template <typename ClassType, typename... ArgsType>
  148. static Callable factory(void);
  149. /*!
  150. * Create a Callable for a constructor with variable args.
  151. * The callable return type is a pointer to ClassType*.
  152. * The user is responsible for managing the memory.
  153. * Template arguments must be explicitly specified.
  154. */
  155. template <typename ClassType, typename... ArgsType>
  156. static Callable factoryNew(void);
  157. /*!
  158. * Create a Callable for a constructor with variable args.
  159. * The callable return type is a std::shared_ptr<ClassType>.
  160. * Template arguments must be explicitly specified.
  161. */
  162. template <typename ClassType, typename... ArgsType>
  163. static Callable factoryShared(void);
  164. private:
  165. std::vector<Object> _boundArgs;
  166. std::shared_ptr<Detail::CallableContainer> _impl;
  167. Callable(Detail::CallableContainer *impl);
  168. POTHOS_API friend bool operator==(const Callable &lhs, const Callable &rhs);
  169. inline friend bool operator!=(const Callable &lhs, const Callable &rhs);
  170. };
  171. /*!
  172. * The equals operators checks if two Callable represent the same internal data.
  173. * The actual bound functions/methods cannot be checked for equality.
  174. * Two callables are only equal if they originated from the same construction.
  175. * \param lhs the left hand object of the comparison
  176. * \param rhs the right hand object of the comparison
  177. * \return true if the objects represent the same internal data
  178. */
  179. POTHOS_API bool operator==(const Callable &lhs, const Callable &rhs);
  180. /*!
  181. * The not-equals operators checks if two Callable do not represent the same
  182. * internal data. The actual bound functions/methods cannot be checked for
  183. * inequality. Two callables are only equal if they originated from the same
  184. * construction.
  185. * \param lhs the left hand object of the comparison
  186. * \param rhs the right hand object of the comparison
  187. * \return true if the objects represent different internal data
  188. */
  189. inline bool operator!=(const Callable &lhs, const Callable &rhs)
  190. {
  191. return !(lhs == rhs);
  192. }
  193. } //namespace Pothos