Ste*_*mer 39 c++ templates type-traits c++11
我正在尝试重新创建Observer模式,我可以将参数完美地转发给观察者的给定成员函数.
如果我尝试传递具有多个覆盖的成员函数的地址,则无法根据参数推断出正确的成员函数.
#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;
}
Run Code Online (Sandbox Code Playgroud)
这无法编译template argument deduction/substitution failed.
请注意,我有Args...,UArgs...因为我需要能够传递参数,这些参数不一定是函数签名类型的相同类型,但可以转换为所述类型.
我以为我可以使用std::enable_if<std::is_convertible<Args, UArgs>>调用消除歧义,但我不相信我可以使用可变参数模板参数包来做到这一点?
如何让模板参数推断在这里工作?
Cas*_*eri 44
问题在于:
l.call(&foo::func, "hello");
l.call(&foo::func, 0.5);
Run Code Online (Sandbox Code Playgroud)
对于这两行,编译器不知道foo::func您指的是哪一行.因此,您必须foo:func通过强制转换提供缺少的类型信息(即类型)来消除歧义:
l.call(static_cast<void (foo::*)(const std::string&)>(&foo::func), "hello");
l.call(static_cast<void (foo::*)(const double )>(&foo::func), 0.5);
Run Code Online (Sandbox Code Playgroud)
或者,您可以提供编译器无法推断的模板参数,并定义以下类型的类型func:
l.call<void, const std::string&>(&foo::func, "hello");
l.call<void, double >(&foo::func, 0.5);
Run Code Online (Sandbox Code Playgroud)
请注意,您必须使用double而不是使用const double上方.其原因是,一般double和const double两种不同的类型.但是,有一种情况,double并且const double被认为是相同的类型:作为函数参数.例如,
void bar(const double);
void bar(double);
Run Code Online (Sandbox Code Playgroud)
不是两个不同的重载,但实际上是相同的功能.
| 归档时间: |
|
| 查看次数: |
14118 次 |
| 最近记录: |