【问题标题】:C++ errors with Variadic template可变参数模板的 C++ 错误
【发布时间】:2018-11-05 21:26:13
【问题描述】:

我有以下代码使用可变参数模板调用std::async,

struct TestParent
{
    template< typename Fn, typeName ...Args >
    bool checkBlock( bool& toCheck,
                     Fn&& fn, Args&& ... args )
    {
        int startIndx = 0;
        int endIndx = 10;
        std::future< bool > tk( std::async( std::launch, fn, this,
                                            startIndx, endIndx, 
                                            toCheck, args ... ) );
        return tk.get();
     }
}

struct TestChild: public TestParent
{
    bool checkRules( const int, const int, bool& std::vector< bool >& );
    bool check();
}

bool TestChild::checkRules( const int startIndx, const int endIndx,
                            bool& toCheck,
                            std::vector< bool >& results )
{
    toCheck = true;
    for ( int indx = startIndx; indx < endIndx; ++ indx )
    {
        bool checkedOk;
        ... do something checking.
        results.push_back( checkedOk );
    }

    return true;
 }

bool TestChild::check()
{
    bool toCheck;
    std::vector< bool > results;
    return checkBlock( toCheck, &testChild::checkRules, this, &results);
}

但我收到以下编译错误消息:

没有匹配函数调用 'async(std::launch, bool (TestChild::&)(int, int, bool&, std::vector&), TestParent, int&, int&, bool&, TestChild*&, std::vector*&)' startInx, endInx, nothingToCheck, args ... ) );

我认为这可能与我将附加参数与参数包一起传递的事实有关。 任何人都知道这有什么问题,我应该怎么做才能让它发挥作用?

【问题讨论】:

  • 在这行代码中:template&lt; typename Fn, typeName ...Args &gt; 第二个参数typeName 是错字吗?同样在这行代码中:bool checkRules( const int, const int, bool&amp; std::vector&lt; bool &gt;&amp; ); 您是否在参数之间缺少逗号?
  • 是的,弗朗西斯。当我在这里输入时,我错过了那个逗号。
  • 我以为你做了,但想确定一下,因为像这样简单的事情会产生与你描述的完全不同的错误。这就是为什么最好尽可能将代码从 IDE 直接复制到堆栈帖子。

标签: c++ variadic-templates stdasync


【解决方案1】:

这是代码中的两个主要问题:

(1) std::async 在将它们转发给提供的函数之前衰减所有传递的参数,这意味着 checkRules 中的引用参数不同于 async 在调用函数时尝试使用的类型,您需要进行以下更改:

template< typename Fn, typename ...Args >
bool checkBlock( std::reference_wrapper<bool> const& toCheck,
                Fn&& fn, Args&& ... args )
{
    int startIndx = 0;
    int endIndx = 10;
    std::future< bool > tk(std::async(std::launch::async,
                                       std::forward<Fn>(fn),
                                       startIndx, endIndx,
                                       toCheck,
                                       std::forward<Args>(args) ... ) );
    return tk.get();
}

(2) 您将this 作为参数传递给checkBlock,最终将作为checkRules 的参数(通过异步调用),但成员函数不接受TestChild* 以匹配@ 987654329@。由于您使用指向 async 的成员函数的指针,因此您需要使用 std::bind 绑定 this 参数并使用 std::wrap 来更改要更改的参数:

#include <functional>
using namespace std::placeholders;

bool TestChild::check()
{
    bool toCheck;
    std::vector< bool > results;
    return checkBlock( std::ref(toCheck), std::bind(&TestChild::checkRules, this, _1, _2, _3, _4), std::ref(results));
}

【讨论】:

  • 哇,答案很好!我错过了自己解决这个问题的两个主要组成部分,你打败了我。我错过了使用std::reference_wrapper 的事实,因为decaystd::ref 我可能最终会继续使用它,但最大的一个是我不熟悉的std::placeholders::_1... 的使用。我很欣赏这种答案,因为我自己学到了一些新东西!恕我直言,我认为您应该得到公认的答案!
  • 非常感谢 Jans!这绝对是向前迈出的一大步,但不幸的是还没有:-(我现在收到一些错误,抱怨“没有名为'type'的类型”如下:功能:1665:61:错误:没有名为'type'的类型' 在'类 std::result_of<:_bind int bool std::vector>&)>(TestChild*, std:: _Placeholder, std::_Placeholder, std::_Placeholder, std::_Placeholder)>(int, int, bool, std::reference_wrapper<:vector> > )>' typedef typename result_of<_callable>::type result_type; 谢谢!
  • 谢谢弗朗西斯!我还将仔细研究 std::placeholders::_1 ...我自己,这对我来说也是新的。
  • @mark 您是否仔细查看了答案中的代码?,在这些更改之后,错误消失了。
  • @Jans:非常感谢 Jans!是的,添加reference_wrapper让错误消失了,现在可以编译了~非常感谢您的帮助!!
【解决方案2】:
return checkBlock( toCheck, &testChild::checkRules, this, &results);

您将 this 与您的 Args 一起传递,这与您的函数的参数不匹配,因此有一个额外的 TestChild*&amp; 不属于。

return checkBlock( toCheck, &testChild::checkRules, ~~this~~, &results);

删除~~这个~~

另外,你应该 std::forward 你的Args 这样:

                                        toCheck, std::forward<Args>(args) ... ) );

【讨论】:

  • 谢谢 Xaxxon!我尝试删除 'this' 并将 std::forward 放到 Args 和 Fn 中,仍然没有用:-(
猜你喜欢
  • 2021-04-19
  • 1970-01-01
  • 2015-01-18
  • 1970-01-01
  • 1970-01-01
  • 2019-07-27
  • 2014-02-01
  • 2022-01-23
相关资源
最近更新 更多