Violet Giraffe
Violet Giraffe

Reputation: 33579

Rvalue reference parameter expires when passed via std::forward?

I have this code that attempts perfect forwarding of template parameters pack into std::function via intermediate class:

#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;
}

Problem: test is called twice, and the second time it's called its parameter is empty pointer. Why?

If I remove std::forward the issue disappears, but that's not what I want.

Upvotes: 1

Views: 76

Answers (1)

Potatoswatter
Potatoswatter

Reputation: 137780

Yes; std::forward does the same thing as std::move when ActualArguments is not a reference type.

In terms of expiration, forward needs to be treated the same as move. Generally you do not forward or move inside a loop.

If you want to move the parameter on the last loop iteration, you'll have to break it out of the loop. That probably means not using the range-for syntax. However, you might ask whether this is a worthwhile optimization, and consider saving it for later when more performance data are available.

Upvotes: 2

Related Questions