Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;模板代表喜欢团结_C++_Templates_Delegates_Variadic - Fatal编程技术网

C++ C++;模板代表喜欢团结

C++ C++;模板代表喜欢团结,c++,templates,delegates,variadic,C++,Templates,Delegates,Variadic,在看到Unity的代表和活动后,我尝试编写自己的代码: 我想创建一个带有可变模板的类,以指定函数的返回类型和可选参数 template <typename Ret, typename... Args> class MyDelegate{ std::vector<Ret(*)(Args...)> vec; public: void operator+=( const Ret(*)(Args...)& newElement) {

在看到Unity的代表和活动后,我尝试编写自己的代码: 我想创建一个带有可变模板的类,以指定函数的返回类型和可选参数

template <typename Ret, typename... Args>
class MyDelegate{
    std::vector<Ret(*)(Args...)> vec;

    public:
    void operator+=( const Ret(*)(Args...)& newElement)
    {
        vec.push_back(newElement);
    }


    Ret operator()(const Args&... args)
    {
        for (auto i = vec.begin(); i != vec.end(); ++i)
            (*i)(args...);
    }
};
我现在对+=运算符有问题,因为VS不接受这个:

MyDelegate<void, int> delegate1;
delegate1 += [](const int a)->void{std::cout << a << std::endl; };
MyDelegate delegate1;

delegate1+=[](const int a)->void{std::cout问题是
std::vector
存储函数指针。它不存储
std::bind
对象,不存储成员函数,不存储functor,也不存储lambda。您试图向其中添加lambda,因此失败

如果要存储支持使用正确参数和返回类型调用的任何类型的对象,则需要
std::function

using FunType = std::function<Ret(Args...)>;
std::vector<FunType> vec;
使用FunType=std::function;
std::vec;


顺便说一句,您可以通过完美地转发
操作符()来改进您的解决方案
args并在界面中复制
newElement
arg并将其移动到
std::vector
问题在于
std::vector
存储函数指针。它不存储
std::bind
对象,不存储成员函数,不存储functor,也不存储lambda。您我们试图向其中添加lambda,因此失败了

如果要存储支持使用正确参数和返回类型调用的任何类型的对象,则需要
std::function

using FunType = std::function<Ret(Args...)>;
std::vector<FunType> vec;
使用FunType=std::function;
std::vec;


顺便说一句,您可以通过完美地转发
操作符()来改进您的解决方案
args并在界面中复制
新元素
arg并将其移动到
std::vector
您的代理只接受函数指针。lambda不是函数指针。但是,您尝试捕获的lambda没有捕获任何内容。这意味着,由于:


在这一点上,您肯定必须使用的建议是
std::function

您的代理只接受函数指针。lambda不是函数指针。但是,您尝试使用的lambda没有捕获任何内容。这意味着它可以转换为函数指针,这要感谢:


在这一点上,您肯定必须使用的
std::function

@TartanLlama是的,std::function就是您所需要的


调用循环可以折叠为(auto handler:vec)handler(args…)的

@TartanLlama的右边,std::function是您所需要的


调用循环可以折叠为
for(auto-handler:vec)handler(args…);

在一个密切相关的主题(延迟调度)中,您可能会发现特别有趣。它对我来说已经方便了很多次。在一个密切相关的主题(延迟调度)中,您可能会发现特别有趣。它对我来说已经方便了很多次。如果您有一个std::vector of std::function,以后可能很难删除单个std::function。通常,如果您想从向量中删除某些内容,您会先找到迭代器,然后将迭代器传递到vector::erase。在std::function的情况下,查找将不起作用,因为std::function的运算符==是…奇怪的(我记不起细节)。相反,你可能想使用一个向量对,其中无符号是某种序列号。然后你可以在以后找到使用该序列号的方法……我对这个问题如此熟悉的唯一原因是我在日常工作中花了几天的时间来做这件事:)如果你有一个std::vector of std::function,它可以是d以后很难删除单个std::function。通常,如果要从向量中删除某些内容,您会首先找到迭代器,然后将迭代器传递到vector::erase。对于std::function,查找将不起作用,因为std::function的运算符==很奇怪(我记不起详细信息)。相反,你可能想使用一个向量对,其中无符号是某种序列号。然后你可以在以后找到使用该序列号的方法……我对这个问题如此熟悉的唯一原因是我在日常工作中花了几天的时间来做这件事:)@TartanLlama超级适合与C库一起使用在require function pointers或Boost.Python,您可能会认为它允许使用函子,但不允许使用。@TartanLlama超级有用,可用于需要函数指针的C库或Boost.Python,您可能会认为它允许使用函子,但不允许。
using FunType = std::function<Ret(Args...)>;
std::vector<FunType> vec;
MyDelegate<void, int> delegate1;
delegate1 += +[](const int a)->void{std::cout << a << std::endl; };
             ↑↑↑
delegate1 += +[x](const int a) { ... }; // error: no match for operator+