Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/144.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何将函数和参数包转发到lambda中,并转发到std::thread的构造函数中?_C++_Multithreading_C++11_Lambda_Perfect Forwarding - Fatal编程技术网

C++ 如何将函数和参数包转发到lambda中,并转发到std::thread的构造函数中?

C++ 如何将函数和参数包转发到lambda中,并转发到std::thread的构造函数中?,c++,multithreading,c++11,lambda,perfect-forwarding,C++,Multithreading,C++11,Lambda,Perfect Forwarding,我希望在C++11中实现一个“可中断的”线程 我已经参数化了我的可中断类,这样它就可以包装任何具有类似构造函数的线程类(用于std::thread,但也应该适用于类似boost::thread的东西(尽管boost::thread已经有了这个功能))。那部分不重要 尽管链接的答案有一些我必须纠正的问题,但它对我来说很有意义,所以我想找出我的错误所在 我已经包括了相关的来源和结果 可中断的 任何人都能对这个问题有所了解,我们将不胜感激 std::thread存储传入其构造函数的参数的衰减副本。对函

我希望在C++11中实现一个“可中断的”线程

我已经参数化了我的可中断类,这样它就可以包装任何具有类似构造函数的线程类(用于std::thread,但也应该适用于类似boost::thread的东西(尽管boost::thread已经有了这个功能))。那部分不重要

尽管链接的答案有一些我必须纠正的问题,但它对我来说很有意义,所以我想找出我的错误所在

我已经包括了相关的来源和结果

可中断的


任何人都能对这个问题有所了解,我们将不胜感激

std::thread
存储传入其构造函数的参数的衰减副本。对函数的引用会经历函数到指针的衰减,这意味着对于
DoStuff
参数,传递给lambda的实际类型是
void(*)(
),而它的
操作符()
仍然期望衰减发生之前的类型参数,即
void(&)(
(推断
F
)。只要您尝试使用
A
参数包中的任何其他参数,就会出现相同的问题

在此上下文中,传递用
std::ref
包装的对象不是一个选项,因为引用包装可能会超过存储在其中的实例的生存期(您实际上不知道什么是
参数
函数
,它们可能是prvalue临时变量,其生命周期在调用
可中断的构造函数后结束。)。当知道某个对象的生存期时,在调用可中断的构造函数时,有人决定将某些实例包装在
std::ref
中可能是合理的,但这里不是这种情况

如果要将参数从
可中断
传输到lambda表达式,然后再传输到
函数
对象所需的副本和移动次数减至最少,则可以选择如下重新编写构造函数:

#include <type_traits>
// ...
template <typename F, typename... A>
interruptible(F&& Function, A&&... Arguments) :
    Interrupted(false),
    Thread(
        [](std::atomic_bool *Interrupted,
           typename std::decay<F>::type&& Function,
           typename std::decay<A>::type&&... Arguments)
        {
            LocalInterrupted = Interrupted;
            Function(std::move(Arguments)...);
        },
        &this->Interrupted,
        std::forward<F>(Function),
        std::forward<A>(Arguments)...
    )
{ }
#包括
// ...
模板
可中断(F&&函数、A&&…参数):
中断(错误),
线(
[](标准::原子布尔*中断,
typename std::decay::类型和函数,
typename std::decage::type&&…参数)
{
局部中断=中断;
函数(std::move(参数)…);
},
&这个->被打断了,
标准::转发(功能),
标准::转发(参数)。。。
)
{ }

清理您的代码:该错误可由90%的代码减少而产生。最少完整的示例,而不是“粘贴我的代码并询问如何修复它”。我将尝试将其浓缩为错误。不过,我的第一次尝试没有成功;如果您确切知道如何生成此错误,将非常感谢您的帮助。最小化:如果您同意@t.c.简化很好地反映了问题,请修改问题以匹配它。请记住,我们更关心错误而不是系统。现在线程函数只接受右值,因此不需要使用
std::forward
。这是您的意图吗?@0x499602D2
std::forward
允许线程的构造函数通过还原ctor调用中使用的表达式的值类别来复制/移动使用完美转发构造的参数。然后它将
std::move()s
这些复制到函数对象(在本例中为lambda),因此它们可以由右值引用绑定,右值引用随后是
std::move
function
。这是有意的,比较它们,然后在内部将它们移动到线程函数的参数中?@0x499602D2线程对象调用函子,就像调用
函数一样(DECAY_COPY(std::forward(f)),DECAY_COPY(std::forward(args))…)
,这意味着:1.这些副本利用完美转发,2.函子的参数始终是右值如果函子的参数始终是右值,它们如何绑定到左值引用?
#include <iostream>
#include <unistd.h>
#include <thread>

#include "interruptible.hpp"

void DoStuff()
{
    try
    {
        while (true)
        {
            std::cout << "Loop" << std::endl;

            sleep(1);

            interruptible<std::thread>::check();
        }
    }
    catch (interrupted_exception const &e)
    {
        std::cout << "Interrupted!" << std::endl;
    }
}


int main()
{
    interruptible<std::thread> a(DoStuff);

    sleep(2);

    std::cout << "Interrupting..." << std::endl;
    a.interrupt();

    sleep(2);

    a->join();

    return 0;
}
/usr/include/c++/4.9.2/functional:1665:61: error: no type named ‘type’ in ‘class std::result_of<interruptible<T>::interruptible(F&&, A&& ...) [with F = void (&)(); A = {}; T = std::thread]::<lambda(std::atomic_bool*, void (&)())>(std::atomic_bool*, void (*)())>’
       typedef typename result_of<_Callable(_Args...)>::type result_type;
                                                             ^
/usr/include/c++/4.9.2/functional:1695:9: error: no type named ‘type’ in ‘class std::result_of<interruptible<T>::interruptible(F&&, A&& ...) [with F = void (&)(); A = {}; T = std::thread]::<lambda(std::atomic_bool*, void (&)())>(std::atomic_bool*, void (*)())>’
         _M_invoke(_Index_tuple<_Indices...>)
         ^
#include <type_traits>
// ...
template <typename F, typename... A>
interruptible(F&& Function, A&&... Arguments) :
    Interrupted(false),
    Thread(
        [](std::atomic_bool *Interrupted,
           typename std::decay<F>::type&& Function,
           typename std::decay<A>::type&&... Arguments)
        {
            LocalInterrupted = Interrupted;
            Function(std::move(Arguments)...);
        },
        &this->Interrupted,
        std::forward<F>(Function),
        std::forward<A>(Arguments)...
    )
{ }