c++ - 你能从模板参数函数签名中提取类型吗

标签 c++ templates c++11

有没有一种方法可以从 foo(bar) 形式的函数签名中提取类型,并仅访问 foobar。所以如果我有模板:

template<typename signiture>
class type{
};

其中 signiture 是 foo(bar) 然后在类中有一个函数读取

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 个参数的函数感兴趣,该函数由特定类实例指定的任何内容确定。

编辑 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;

};

它是 Observer 模式的一个实现,它是非虚拟的,使用 std::function 将两者粘合在一起。我想使用 foo(bar) 语法,因为它更有利于类的易用性。问题是将函数类型签名转换为返回类型和参数类型,以便在主题类中指定正确的 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>{}, "!");
}

关于c++ - 你能从模板参数函数签名中提取类型吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28033251/

相关文章:

c++ - 带有模板的 CUDA 内核启动宏

c++ - 模板 ID 与任何模板声明都不匹配

c++ - 是否可以使用 c++11 中的模板元编程创建一个填充大小为 N 的零的 vector

c++ - 创建boost::shared_ptr的深层拷贝

c++ - 根据迭代器声明容器 const 或 non-const

c++ - 在 C++11 中使用 sort 函数有什么问题?

c++ - 使用指针的 strcat 实现

c++ - 在循环双向链表的第一个节点之前/之后插入的算法是什么?

c++ - 使用函数的返回类型作为另一个模板函数调用

c++ - 模板模板类中非类型参数的类型在 C++14 中不可推导,但在 C++17 中可推导