Я пытаюсь воссоздать шаблон наблюдателя, в котором я могу точно передать параметры заданной функции-члену наблюдателей.
Если я попытаюсь передать адрес функции-члена, которая имеет несколько переопределений, она не сможет определить правильную функцию-член на основе аргументов.
#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
, проблема лежит на более высоком уровне. Кроме того, очень важно: не используйтеstd::forward
внутриcall
для аргументов, так как таким образом они потенциально пересылаются несколько раз, и только один из наблюдателей получает неперемещенный аргумент для rvalue. - person Xeo   schedule 26.07.2013