Ссылочный параметр Rvalue истекает при передаче через std::forward?
У меня есть этот код, который пытается совершенную пересылку пакета параметров шаблона в 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 ответ
Да; std::forward
делает то же самое, что и std::move
когда ActualArguments
не является ссылочным типом.
С точки зрения срока годности, forward
нужно относиться так же, как move
, Как правило, вы не forward
или же move
внутри петли.
Если вы хотите переместить параметр на последней итерации цикла, вам придется вырвать его из цикла. Это, вероятно, означает, что вы не используете синтаксис диапазона. Однако вы можете спросить, является ли это полезной оптимизацией, и подумать о том, чтобы сохранить ее на потом, когда будет доступно больше данных о производительности.