正在变量模板中复制的参考参数

Reference parameter being copied in variadic template

本文关键字:复制 参考 参数 变量      更新时间:2023-10-16

我有一个Event类,它将weak_ptr(观察器)的一组元组存储到一个函数中,该函数在事件"激发"时执行。

函数类型为:void(int&)。也就是说,我想激发传递对某个值的引用的事件,让观察者更改该值,并验证该值在被观察对象中是否已更改回。顺便说一句,事件实现是可变的,这可能会使问题复杂化(至少是代码)。

目前这是失败的。在这条线上的某个地方,引用正在被转换为非引用或复制,但我看不出在哪里。

全额回购低于。注意assert(value!=10)失败,即使我在事件处理程序中将值设置为1。

#include <memory>
#include <tuple>
#include <vector>
#include <cassert>
#include <functional>
template<class FunctionPrototype>
class Event
{
public:
    template<typename... Args>
    void operator()(Args... args)
    {
        for (auto const & listener : Listeners)
        {
            if (auto locked = std::get<0>(listener).lock())
                std::get<1>(listener)(args...);
        }       
    }
    template<typename P, typename Q, typename R, typename... Args>
    void Attach(P(Q::*f)(Args...), std::shared_ptr<R> const & p)
    {
        auto w = std::weak_ptr<R>(p);
        auto l = [w, f](Args... args) {
            if (auto locked = w.lock())
                return (*locked.get().*f)(args...);
            else
                return P();
        };
        Listeners.push_back(std::make_tuple(std::weak_ptr<void>(w), l));        
    }
    typedef std::tuple<std::weak_ptr<void>, std::function<FunctionPrototype>> event_tuple;
    std::vector<event_tuple> Listeners;
};
class Observed : public std::enable_shared_from_this < Observed >
{
public:
    int value;
    void Fire()
    {
        value = 10;
        TheEvent(value);
        assert(value != 10);
    }
    Event<void(int &)> TheEvent;
};
class Observer : public std::enable_shared_from_this<Observer>
{
public:
    void Attach(std::shared_ptr<Observed> const & observed)
    {
        observed->TheEvent.Attach(&Observer::OnEvent, shared_from_this());
    }
    void OnEvent(int & value)
    {
        assert(value == 10);
        value = 1;
    }
};
int main(void)
{
    auto observed = std::make_shared<Observed>();
    auto observer1 = std::make_shared<Observer>();
    observer1->Attach(observed);
    observed->Fire();
    return 0;
}

Event::operator()按值获取参数。重写如下:

template<typename... Args>
void operator()(Args&&... args)
{
    for (auto const & listener : Listeners)
    {
        if (auto locked = std::get<0>(listener).lock())
            std::get<1>(listener)(std::forward<Args>(args)...);
    }       
}