我有一个带有函数add的类:
class Pool {
public:
Pool() {};
template<class F, class... A>
auto add(F&& f, A&&... args) -> std::future<typename std::result_of<F(A...)>::type>
{
// return empty placeholder, for the sake of this code example
std::future<typename std::result_of<F(A...)>::type> ret;
return ret;
};
};
它应该接受任何函数及其参数,将其添加到线程池并返回该函数结果类型的 future 。
还有一个我使用它的类:
class MyClass {
public:
string doIt(string) { return string("a"); };
string doIt(int, string) { return string("b"); };
void test() {
Pool myPool;
string a("test");
myPool.add(&MyClass::doIt, a); // Error
};
};
这给出了一个编译器错误:
Error 1 error C2914: 'Pool::add' : cannot deduce template argument as function argument is ambiguous MyClass.cpp 94
现在的问题是(我认为)编译器无法推断出我想使用哪个重载。类似于 Overloaded function as argument of variadic template function . (另外,我不是 100% 清楚为什么我必须对类成员函数使用“&”,但如果我传入一个自由函数则没有符号)。 无论如何,我也尝试了上面答案中提到的解决方法:
struct doIt_wrapper {
template <typename... T>
auto operator()(T... args) -> decltype(doIt(args...)) {
return doIt(args...);
}
};
然后将 MyClass::test() 修改为:
void test() {
Pool myPool;
string a("test");
myPool.add(doIt_wrapper(), a);
};
但它也给我一个编译器错误:
error C2893: Failed to specialize function template 'unknown-type doIt_wrapper::operator ()(T...)' C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\xrefwrap 58
我还尝试了一些变体,例如 myPool.add(doIt_wrapper<string>()
有/没有“&”,但它们都会产生一个或另一个编译器错误。
我想我还没有完全理解这个问题,如果有人能阐明它,我会很高兴。我也在寻找解决这个问题的合适方法。这不可能真的只有在没有两个同名函数的情况下才有效,并且一旦存在,如果没有适当的通用解决方案,一切都会崩溃?
编辑:修正了一些拼写错误并在此处上传了一个最小示例:http://ideone.com/eX1r1l
最佳答案
正如其他人所提到的,问题在于 doIt()
在 doIt_wrapper
类中不可调用,因为它还需要一个指向所调用对象的指针。
您可以只修改 doIt_wrapper
operator()
以获取指向对象的指针并将指向 this
的指针作为第一个参数传递给 添加()
。
它看起来像这样:
#include <iostream>
#include <future>
using namespace std;
class Pool {
public:
Pool() {};
template<class F, class... A>
auto add(F&& f, A&&... args) -> std::future<typename std::result_of<F&&(A&&...)>::type>
{
// return empty placeholder, for the sake of this code example
std::future<typename std::result_of<F&&(A&&...)>::type> ret;
return ret;
};
};
class MyClass {
public:
string doIt(string) { return string("a"); };
string doIt(int, string) { return string("b"); };
struct doIt_wrapper
{
template<class T, class... Ts>
auto operator()(T&& t, Ts&&... args) -> decltype(t->doIt(std::forward<Ts>(args)...))
{
return t->doIt(std::forward<Ts>(args)...);
}
};
void test() {
Pool myPool;
string a("test");
myPool.add(doIt_wrapper(), this, a); // No error no more
};
};
int main() {
// your code goes here
MyClass my;
my.test();
return 0;
}
这样您就不必进行强制转换。代码在 GCC 和 Clang 上编译。
关于c++ - 将重载的成员函数传递给可变模板函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26426728/