c++ - 将重载的成员函数传递给可变模板函数

标签 c++ c++11 variadic-templates

我有一个带有函数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/

相关文章:

c++ - 如果在 C++ 中的基类中添加虚函数或非虚函数,是否必须重新编译整个类层次结构?

c++ - std::promise 能否知道相应的 std::future 已取消等待?

c++ - 完美转发 l-value ref 和 r-value ref 和非 ref 类型的可变参数模板?

c++ - 使用 {fmt} 和 source_location 创建基于可变参数模板的日志功能

c++ - 用标准 C++ 函数替换 QByteArray

c++ - 现代编译器是否优化了 unsigned int 在 for 循环中的使用?

c++ - for循环递减不起作用

c++ - 燃气发动机上的计算机驱动点火正时如何工作?

c++ - 注意 : 'std::thread' is defined in header '<thread>' ; did you forget to '#include <thread>' ?

c++ - 如何提取/扩展可变模板参数