你能从模板参数函数签名中提取类型吗
Can you extract types from template parameter function signature
有没有一种方法可以从 foo(bar)
形式的函数签名中提取类型并仅访问 foo
或 bar
。所以如果我有模板:
template<typename signiture>
class type{
};
其中签名是 foo(bar)
然后在 class 中有一个函数读取
foo function(bar b){
//do stuff
}
我正在与 std::function
交互,发现使用 foo(bar)
语法比像这样使用多个模板参数更方便:
template<typename return_t,param_tps... args>
class type{
return_t function(param_ps args...){
return something;
}
};
让我知道是否可以澄清一下?
提前致谢。
编辑:
为了澄清起见,我对具有 N 个参数的函数感兴趣,该函数由特定 class 实例指定的任何内容确定。
编辑 2:
这个问题基于的代码如下:
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;
};
它是非虚拟的观察者模式的实现,使用 std::function
将两者粘合在一起。我想使用 foo(bar)
语法,因为它更有利于 classes 的一切易用性。问题是将函数类型签名转换为 return 类型和参数类型,以便在主题 class 中指定正确的 operator()
,以便它可以用正确的数据通知观察者.
所做的更改基于下面给出的示例:
template<typename t>struct type;
template<typename R,typename... args_t>
struct type<R(args_t...)>{
//use R and args_t as needed
}
感谢所有帮助过的人。
这是一个非常基本的解决方案,适用于接受一个参数的函数(看起来你在问题中放置了这个约束,但是一个通用的解决方案很容易提供,如下所示):
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..
};
这是一个可能的例子 (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>{}, "!");
}
如果您对可变情况的更通用的解决方案感兴趣,这可能就是您正在寻找的:
#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..
};
这是一个可能的用法示例 (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>{}, "!");
}
有没有一种方法可以从 foo(bar)
形式的函数签名中提取类型并仅访问 foo
或 bar
。所以如果我有模板:
template<typename signiture>
class type{
};
其中签名是 foo(bar)
然后在 class 中有一个函数读取
foo function(bar b){
//do stuff
}
我正在与 std::function
交互,发现使用 foo(bar)
语法比像这样使用多个模板参数更方便:
template<typename return_t,param_tps... args>
class type{
return_t function(param_ps args...){
return something;
}
};
让我知道是否可以澄清一下? 提前致谢。
编辑: 为了澄清起见,我对具有 N 个参数的函数感兴趣,该函数由特定 class 实例指定的任何内容确定。
编辑 2: 这个问题基于的代码如下:
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;
};
它是非虚拟的观察者模式的实现,使用 std::function
将两者粘合在一起。我想使用 foo(bar)
语法,因为它更有利于 classes 的一切易用性。问题是将函数类型签名转换为 return 类型和参数类型,以便在主题 class 中指定正确的 operator()
,以便它可以用正确的数据通知观察者.
所做的更改基于下面给出的示例:
template<typename t>struct type;
template<typename R,typename... args_t>
struct type<R(args_t...)>{
//use R and args_t as needed
}
感谢所有帮助过的人。
这是一个非常基本的解决方案,适用于接受一个参数的函数(看起来你在问题中放置了这个约束,但是一个通用的解决方案很容易提供,如下所示):
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..
};
这是一个可能的例子 (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>{}, "!");
}
如果您对可变情况的更通用的解决方案感兴趣,这可能就是您正在寻找的:
#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..
};
这是一个可能的用法示例 (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>{}, "!");
}