【问题标题】:C++ async with variadic template can not find correct function template specialization带有可变参数模板的 C++ 异步找不到正确的函数模板特化
【发布时间】:2015-06-28 19:47:51
【问题描述】:

我有一个带有成员函数f的类,我用可变参数模板和forward包装它来制作另一个成员函数rf(只需在f末尾添加一个特定参数即可有点不同)。然后,我通过用async 包装rf 来创建另一个成员函数async_rf,但它不起作用。我尝试通过用额外的特定参数包装f 来制作async_rf,它可以工作。

代码:

#include <future>         // std::async, std::future
#include <iostream>

class test {

public:

    void f(int tmp, bool reverse = 0)
    {
        std::cout << tmp << " | " << reverse << std::endl;
    }

    template<typename... Args>
    void rf(Args... args)
    {
        f(std::forward<Args>(args)..., 1);
    }

    template<typename... Args>
    std::future<void> async_rf(Args... args)
    {
        // doesn't work
        return std::async (&test::rf, this, std::forward<Args>(args)...);

        // work
        return std::async (&test::f, this, std::forward<Args>(args)..., 1);
    }

};


int main()
{
    test s;
    auto tmp = s.async_rf(10);
    tmp.get();
    return 0;
}

这是编译时的错误信息:

(叮当声)

$ clang++ --version
clang version 3.6.1 (tags/RELEASE_361/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
$ clang++ -std=c++14 -Wall -lpthread src/test.cpp -o bin/test
src/test.cpp:23:16: error: no matching function for call to 'async'
        return std::async (&test::rf, this, std::forward<Args>(args)...);
               ^~~~~~~~~~
src/test.cpp:35:18: note: in instantiation of function template specialization 'test::async_rf<int>' requested here
    auto tmp = s.async_rf(10);
                 ^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/5.1.0/../../../../include/c++/5.1.0/future:1723:5: note: candidate template
      ignored: couldn't infer template argument '_Fn'
    async(_Fn&& __fn, _Args&&... __args)
    ^
/usr/bin/../lib64/gcc/x86_64-unknown-linux-gnu/5.1.0/../../../../include/c++/5.1.0/future:1703:5: note: candidate template
      ignored: substitution failure [with _Fn = test *, _Args = <int>]: no type named 'type' in
      'std::result_of<test *(int)>'
    async(launch __policy, _Fn&& __fn, _Args&&... __args)
    ^
1 error generated.

(gcc)

$ g++ --version
g++ (GCC) 5.1.0
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ g++ -std=c++14 -Wall -lpthread src/test.cpp -o bin/test
src/test.cpp: In instantiation of ‘std::future<void> test::async_rf(Args ...) [with Args = {int}]’:
src/test.cpp:35:29:   required from here
src/test.cpp:23:27: error: no matching function for call to ‘async(<unresolved overloaded function type>, test*, int)’
         return std::async (&test::rf, this, std::forward<Args>(args)...);
                           ^
In file included from src/test.cpp:1:0:
/usr/include/c++/5.1.0/future:1703:5: note: candidate: template<class _Fn, class ... _Args> std::future<typename std::result_of<_Functor(_ArgTypes ...)>::type> std::async(std::launch, _Fn&&, _Args&& ...)
     async(launch __policy, _Fn&& __fn, _Args&&... __args)
     ^
/usr/include/c++/5.1.0/future:1703:5: note:   template argument deduction/substitution failed:
src/test.cpp:23:27: note:   cannot convert ‘&((test*)this)->*test::rf’ (type ‘<unresolved overloaded function type>’) to type ‘std::launch’
         return std::async (&test::rf, this, std::forward<Args>(args)...);
                           ^
In file included from src/test.cpp:1:0:
/usr/include/c++/5.1.0/future:1723:5: note: candidate: template<class _Fn, class ... _Args> std::future<typename std::result_of<_Functor(_ArgTypes ...)>::type> std::async(_Fn&&, _Args&& ...)
     async(_Fn&& __fn, _Args&&... __args)
     ^
/usr/include/c++/5.1.0/future:1723:5: note:   template argument deduction/substitution failed:
src/test.cpp:23:27: note:   couldn't deduce template parameter ‘_Fn’
         return std::async (&test::rf, this, std::forward<Args>(args)...);
                           ^

有没有人可以提供更多关于它为什么不起作用的详细信息?为什么编译器找不到正确的模板特化?

【问题讨论】:

    标签: c++ templates asynchronous variadic-templates


    【解决方案1】:

    要求编译器通过提供给async 的参数来推断rf 的特化,这将需要它查看async 的实现,这有点过分了。

    只需自己指定模板参数即可:

    return std::async (&test::rf<Args...>, this, std::forward<Args>(args)...);
    

    顺便说一句,您可能想在任何地方将Args... 更改为Args&amp;&amp;...,否则参数将按值传递。

    【讨论】:

      【解决方案2】:

      由于rf 是一个函数模板,你不能简单地将它传递给std::async。首先,您必须指定它的模板参数,即Args...。所以你的函数看起来像:

      template<typename... Args>
      std::future<void> async_rf(Args... args)
      {
          // doesn't work
          return std::async (&test::rf<Args...>,this,std::forward<Args>(args)...);
      
          // work
          return std::async (&test::f, this, std::forward<Args>(args)..., 1);
      }
      

      虽然在该函数中有 2 个返回语句可能不是您想要做的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-08
        • 2017-10-15
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多