Can you extract types from the signature of a parameter of a template parameter

Is there a way to extract types from a function signature in the form foo(bar) and access only foo or bar . Therefore, if I have a template:

 template<typename signiture> class type{ }; 

where signiture foo(bar) and then a function in the class that reads

 foo function(bar b){ //do stuff } 

I interact with std::function and found it more convenient to use the foo(bar) syntax instead of using several template parameters, for example:

 template<typename return_t,param_tps... args> class type{ return_t function(param_ps args...){ return something; } }; 

Let me know, can I clarify, please? Thanks at Advance.

EDIT: to clarify, I'm interested in a function with N number of parameters that will be defined by any particular instance of the class.

EDIT 2: The code on which this question is based is as follows:

 using std::function; template <typename signiture> class Observer; template <typename return_t, typename ...args_t> class Observer<return_t(args_t...)> { protected: using signature = return_t(args_t...); typedef function<signature> func_t; ~Observer(){} func_t what_to_do; public: Observer(Subject<signature>& subject,func_t what):what_to_do(what){ subject.Attach(what_to_do); } return_t operator()(args_t... args){ what_to_do(args...); } }; using std::function; using std::vector; template <typename signature> class Subject; template <typename return_t,typename...param_tps> class Subject<return_t(param_tps...)> { using signature=return_t(param_tps...); public: void Attach(std::function<signature> o){ obs.push_back(o); } void operator()(param_tps... params){ for (typename vector<std::function<signature>>::const_iterator i=obs.begin(); i!=obs.end(); ++i) { (*i)(params...); } } protected: ~Subject(){} vector<std::function<signature>> obs; }; 

This is an implementation of the Observer pattern, which is not virtual, using std::function to glue things in between. I wanted to use the syntax foo(bar) , because all this contributes more to the ease of use of classes. The problem was converting the signature of the function type to the return type and parameter types to indicate the correct operator() in the theme class so that it could notify observers with the correct data.

The changes that were made were based on the example below:

 template<typename t>struct type; template<typename R,typename... args_t> struct type<R(args_t...)>{ //use R and args_t as needed } 

Thanks to everyone who helped.

+6
source share
1 answer

Here is a very simple solution that works for functions that take one parameter (it seems you put this restriction in the question, but a generalized solution is pretty easy to provide, as shown below):

 template<typename S> struct type; // You can leave this undefined, because the template is // supposed to be instantiated with a function type, and // that is matched by the specialization below. template<typename R, typename Arg> struct type<R(Arg)> { // Just use R and Args as you wish here.. }; 

Here's a possible example ( live demo on Coliru ):

 #include <type_traits> template<typename S> struct signature; template<typename R, typename Arg> struct signature<R(Arg)> { using return_type = R; using argument_type = Arg; }; int main() { using ret = signature<void(int)>::return_type; using arg = signature<void(int)>::argument_type; static_assert(std::is_same<ret, void>{}, "!"); static_assert(std::is_same<arg, int>{}, "!"); } 

If you are interested in a more general solution for the variational case, this is probably what you are looking for:

 #include <tuple> struct type; // You can leave this undefined, because the template is // supposed to be instantiated with a function type, and // that is matched by the specialization below. template<typename R, typename... Args> struct type<R(Args...)> { // Just use R and Args... as you with here.. }; 

And here is a usage example ( live demo on Coliru ):

 #include <tuple> #include <type_traits> template<typename S> struct signature; template<typename R, typename... Args> struct signature<R(Args...)> { using return_type = R; using argument_type = std::tuple<Args...>; }; int main() { using ret = signature<void(int, double)>::return_type; using arg1 = std::tuple_element_t<0, signature<void(int, double)>::argument_type>; using arg2 = std::tuple_element_t<1, signature<void(int, double)>::argument_type>; static_assert(std::is_same<ret, void>{}, "!"); static_assert(std::is_same<arg1, int>{}, "!"); static_assert(std::is_same<arg2, double>{}, "!"); } 
+6
source

Source: https://habr.com/ru/post/981240/


All Articles