【发布时间】:2013-07-26 07:38:22
【问题描述】:
我正在尝试重新创建 观察者模式,我可以在其中完美地将参数转发给观察者的给定成员函数。
如果我尝试传递具有多个覆盖的成员函数的地址,它无法根据参数推断出正确的成员函数。
#include <iostream>
#include <vector>
#include <algorithm>
template<typename Class>
struct observer_list
{
template<typename Ret, typename... Args, typename... UArgs>
void call(Ret (Class::*func)(Args...), UArgs&&... args)
{
for (auto obj : _observers)
{
(obj->*func)(std::forward<UArgs>(args)...);
}
}
std::vector<Class*> _observers;
};
struct foo
{
void func(const std::string& s)
{
std::cout << this << ": " << s << std::endl;
}
void func(const double d)
{
std::cout << this << ": " << d << std::endl;
}
};
int main()
{
observer_list<foo> l;
foo f1, f2;
l._observers = { &f1, &f2 };
l.call(&foo::func, "hello");
l.call(&foo::func, 0.5);
return 0;
}
使用template argument deduction/substitution failed 编译失败。
请注意,我有 Args... 和 UArgs...,因为我需要能够传递的参数不一定与函数签名的类型相同,但可以转换为所述类型。
我在想我可以使用 std::enable_if<std::is_convertible<Args, UArgs>> 调用来消除歧义,但我不相信我可以使用可变参数模板参数包来做到这一点?
如何让模板参数推导在这里起作用?
【问题讨论】:
-
call怎么改都没关系,问题就在这上面。另外,非常重要:不要在call中使用std::forward作为参数,因为它们可能会以这种方式多次转发,并且只有一个观察者会收到未移动的右值参数。
标签: c++ templates c++11 typetraits