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++_Templates_C++11_Bind_Variadic Templates - Fatal编程技术网

C++ 绑定可变模板参数时副本过多

C++ 绑定可变模板参数时副本过多,c++,templates,c++11,bind,variadic-templates,C++,Templates,C++11,Bind,Variadic Templates,我正在创建一个作业队列。该作业将在线程A中创建,然后该作业将被发送到线程B,线程B将执行该作业。作业完成后,作业将被发送回线程A #include <functional> #include <iostream> #include <memory> using namespace std; template<typename T, typename... Args> class Job { public: Job(std

我正在创建一个作业队列。该作业将在线程A中创建,然后该作业将被发送到线程B,线程B将执行该作业。作业完成后,作业将被发送回线程A

#include <functional>
#include <iostream>
#include <memory>

using namespace std;

template<typename T, typename... Args>
class Job
{
    public:
        Job(std::weak_ptr<T> &&wp, std::function<void(const Args&...)> &&cb)
            : _cb(std::move(cb)), 
              _cbWithArgs(), 
              _owner(std::move(wp)) {}

    public:
        template<typename... RfTs>
        void bind(RfTs&&... args)
        {
            // bind will copy args for three times.
            _cbWithArgs = std::bind(_cb, std::forward<RfTs>(args)...);
        }

        void fire()
        {
            auto sp = _owner.lock();
            if (sp)
            {
                _cbWithArgs();
            }
        }

    private:
        std::function<void(const Args& ...)> _cb;
        std::function<void()> _cbWithArgs;
        std::weak_ptr<T> _owner;
};

struct Args
{
    Args() = default;
    Args(const Args &args)
    {
        cout << "Copied" << endl;
    }
};

struct Foo
{
    void show(const Args &)
    {
        cout << "Foo" << endl;
    }
};

int main()
{
    using namespace std::placeholders;

    shared_ptr<Foo> sf (new Foo());
    Args args;

    // Let's say here thread A created the job.
    Job<Foo, Args> job(sf, std::bind(&Foo::show, sf.get(), _1));

    // Here thread B has finished the job and bind the result to the
    // job. 
    job.bind(args);

    // Here, thread A will check the result.
    job.fire();
}
有三份!不可接受,我不知道我哪里做错了。为什么是三份?我在谷歌上搜索并找到了一个方法:,它只复制了一次参数。但它必须在构造函数中初始化bind函数

谢谢,Piotr Skotnicki。不幸的是,我没有C++14编译器。那么,让我们让Args可以移动:

struct Args
{
    Args() = default;
    Args(const Args &args)
    {
        cout << "Copied" << endl;
    }
    Args(Args &&) = default;
    Args& operator=(Args &&) = default;
};
struct Args
{
Args()=默认值;
参数(常量参数和参数)
{

cout第一个副本由
std::bind
本身制作:

std::bind(_cb, std::forward<RfTs>(args)...)
18效果:
函数(std::forward(f)).swap(*this);

其中:


不幸的是,我没有在VC14中编译,std::tuple需要initialize@MORTAL“不幸的是,我没有在VC14中编译,std::tuple需要初始化”,您能详细说明一下吗?感谢您提供的信息性答案,我在VC14中运行了您的代码,但它没有编译,它返回错误为
tuple(67):错误C2476:'constexpr'构造函数未初始化所有成员
。我不知道这是否是另一个与VC14@MORTAL很可能是bug@softfmla似乎将
Args()=default;
更改为
Args(){}
使代码在MSVC中编译。通过使
Args
可移动,您只能用移动来替换副本,这仍然没有达到可能的效率
std::bind(_cb, std::forward<RfTs>(args)...)
template<class F> function& operator=(F&& f);
template<class F> function(F f);
template <typename T, typename... Args>
class Job
{
public:
    Job(std::weak_ptr<T> wp, std::function<void(const Args&...)> &&cb)
        : _cb(std::move(cb)), 
          _owner(wp) {}

public:
    template<typename... RfTs>
    void bind(RfTs&&... args)
    {
        _args = std::forward_as_tuple(std::forward<RfTs>(args)...);
    }

    void fire()
    {
        auto sp = _owner.lock();
        if (sp)
        {
            apply(std::index_sequence_for<Args...>{});
        }
    }

private:    
    template <std::size_t... Is>
    void apply(std::index_sequence<Is...>)
    {
        _cb(std::get<Is>(_args)...);
    }

    std::function<void(const Args&...)> _cb;
    std::weak_ptr<T> _owner;
    std::tuple<Args...> _args;
};