我正试图使用C++11来定义一个类,该类可以存储多个std::function<>
,并根据它们的参数类型调用它们,类似于重载解析。
我为"重载"函数应该支持的每个函数签名声明一个基类:
template <typename R, typename... A>
struct overload;
template <typename R, typename... A>
struct overload<R(A...)>
{
typedef std::function<R(A...)> F;
F f_;
overload(F f): f_(f) {}
R operator()(A... a)
{
return f_(a...);
}
};
template <typename... T>
struct overloaded_function : public overload<T>...
{
overloaded_function(T... t): overload<T>(t)... {}
};
int main()
{
overloaded_function<void(float), void(int, int)> f([](float){}, [](int, int){});
f(1.F); // build error
f(2, 3); // build error
return 0;
}
生成错误:(Visual Studio 2013)
"重载::operator()[其中R=void,A=]"不明确c: \Users\benj7280\Documents\kernel_builder\src\main.cpp 39 5 kernel_bBuilder
我不明白运算符怎么会模棱两可,因为函数有完全不同的签名。当我只使用具体类完全删除模板时,以及当我用命名成员函数替换operator()
重载时,错误完全相同。
您需要将基类operator()
s包含在using
中。然而,我不知道如何使用参数包来做到这一点,所以希望其他人能加入并回答这个问题。
我能做的是重做你的结构,使它一直线性继承,每个重载只需要using
下一个:
template <typename... T>
struct overloads
{
// need this one so that the last overload has
// something to "using". If you have an overload for void(),
// that one will hide this one. If you don't, and call f(),
// this won't compile... which is fine.
void operator()();
};
template <typename R, typename... A, typename... T>
struct overloads<R(A...), T...>
: overloads<T...>
{
typedef std::function<R(A...)> F;
F f_;
template <typename... Fs>
overloads(F f, Fs... fs)
: overloads<T...>(fs...)
, f_(f)
{}
using overloads<T...>::operator();
R operator()(A... a)
{
return f_(a...);
}
};
template <typename... T>
struct overloaded_function : public overloads<T...>
{
overloaded_function(T... t)
: overloads<T...>(t...)
{ }
};
现在您的f(1.F)
和f(2, 3)
调用都是compile,因为现在所有的重载都是。。。过载。