Rvalue引用参数在通过std :: forward传递时到期?

时间:2014-12-29 10:41:38

标签: c++11 rvalue-reference

我有这个代码尝试通过中间类完美地将模板参数包转发到std::function

#include <functional>
#include <vector>
#include <algorithm>
#include <iterator>
#include <memory>
#include <iostream>

template <typename ...Arguments>
class CSignal
{
public:
    typedef std::function<void (Arguments...)> SignalFunction;
public:
    void connect(const SignalFunction& target)
    {
        m_connections.emplace_back(std::make_shared<SignalFunction>(target));
    }

    template <typename ...ActualArguments>
    void invoke(ActualArguments&&... args) const
    {
        for (auto& connection: m_connections)
            if (connection)
                (*connection)(std::forward<ActualArguments>(args)...);
    }

private:
    std::vector<std::shared_ptr<SignalFunction>> m_connections;
};


struct A
{
    void f() {std::cout << __FUNCTION__ << "\n";}
};

void test(std::shared_ptr<A> ptr)
{
    if (ptr)
        ptr->f();
}

int main()
{
    CSignal<std::shared_ptr<A>> signal;
    signal.connect(test);
    signal.connect(test);

    signal.invoke(std::make_shared<A>());

    return 0;
}

问题:test被调用两次,第二次调用它的参数是empty指针。为什么呢?

如果我删除std::forward,问题就会消失,但那不是我想要的。

1 个答案:

答案 0 :(得分:2)

是;当std::forward不是引用类型时,std::move会与ActualArguments做同样的事情。

就到期而言,forward需要与move一样对待。通常,您不会在循环中forwardmove

如果要在最后一次循环迭代中移动参数,则必须将其从循环中分离出来。这可能意味着不使用range-for语法。但是,您可能会问这是否值得进行优化,并考虑在以后提供更多性能数据时将其保存。