如何将可变参数传递给std :: thread?

公平

我想通过包装来自C ++ 11的std :: thread类来使用自己的Thread实现,这样我就可以处理所需的异常。

这是我的包装类:

#include <Types.hpp>
#include <thread>
#include <exception>
#include <functional>

class Thread
{
    private:

        std::exception_ptr exceptionPtr;
        std::thread thread;

    public:

        using Id = std::thread::id;

        using NativeHandleType = std::thread::native_handle_type;

        Thread() noexcept = default;
        Thread(Thread &&t) noexcept :
            exceptionPtr(std::move(t.exceptionPtr)),
            thread(std::move(t.thread))
        {
        }

        Thread &operator =(Thread &&t) noexcept
        {
            exceptionPtr = std::move(t.exceptionPtr);
            thread = std::move(t.thread);
            return *this;
        }

        template<typename Callable, typename... Args>
        Thread(Callable &&f, Args &&... args) :
            exceptionPtr(nullptr),
            thread([&](Callable &&f, Args &&... args)
            {
                try
                {
                    std::once_flag flag;
                    std::call_once(flag, f, args...);
                }
                catch (...)
                {
                    exceptionPtr = std::current_exception();
                }

            }, f, args...)
        {
            if (exceptionPtr != nullptr)
            {
                 std::rethrow_exception(exceptionPtr);
            }
        }

        bool joinable() const noexcept
        {
            return thread.joinable();
        }

        void join()
        {
            thread.join();
        }

        void detach()
        {
            thread.detach();
        }

        Id getId() const noexcept
        {
            return thread.get_id();
        }

        NativeHandleType nativeHandle()
        {
            return thread.native_handle();
        }

        static uint32_t hardwareConcurrency() noexcept
        {
            return std::thread::hardware_concurrency();
        }

        static void wait(Time t)
        {
            std::this_thread::sleep_for(t);
        }
};

如果没有参数,则效果很好:

Thread([&]() {  /* do something */ }).detach();

...但是如果我尝试传递可变参数:

Thread(&GUI::refreshTask, this, refreshDelay).detach();

...我在编译时出错:

buildroot-2014.02 / output / host / usr / i586-buildroot-linux-uclibc / include / c ++ / 4.8.2 / functional:在'struct std :: _ Bind_simple)的实例中(std :: chrono :: duration>); Args = {CRH :: GUI const,std :: chrono :: duration>&}] :: ____ lambda1(void(CRH :: GUI :: )(std :: chrono :: duration>),CRH :: GUI,std :: chrono :: duration>)>':buildroot-2014.02 / output / host / usr / i586-buildroot-linux-uclibc / include / c ++ / 4.8.2 / thread:137:47:需要'std :: thread :: thread(_Callable &&,_Args && ...)[with _Callable = CRH :: Thread :: Thread(Callable &&,Args && ...)[with Callable = void(CRH :: GUI :: )(std :: chrono ::持续时间>); Args = {CRH :: GUI const,std :: chrono :: duration>&}] :: __ lambda1; _Args = {void(CRH :: GUI :: &)(std :: chrono :: duration>),CRH :: GUIconst&,std :: chrono :: duration>&}]]'/home/cyril/Documents/crh-2016/src/robot2/../core/Thread.hpp:72:30:要求来自'CRH :: Thread: :Thread(Callable &&,Args && ...)[with Callable = void(CRH :: GUI :: )(std :: chrono :: duration>); Args = {CRH :: GUI const,std :: chrono :: duration>&}]'src / core / GUI.cpp:90:57:从此处需要buildroot-2014.02 / output / host / usr / i586-buildroot- linux-uclibc / include / c ++ / 4.8.2 / functional:1697:61:错误:在'class std :: result_of)(std :: chrono :: duration>)中没有名为'type'的类型; Args = {CRH :: GUI const,std :: chrono :: duration>&}] :: __ lambda1(void(CRH :: GUI :: )(std :: chrono :: duration>),CRH :: GUI,std :: chrono :: duration>)>'typedef typename result_of <_Callable(_Args ...)> :: type result_type; ^ buildroot-2014.02 / output / host / usr / i586-buildroot-linux-uclibc / include / c ++ / 4.8.2 / functional:1727:9:错误:'class std :: result_of)中没有名为'type'的类型( std :: chrono :: duration>); Args = {CRH :: GUI const,std :: chrono :: duration>&}] :: ____ lambda1(void(CRH :: GUI :: )(std :: chrono :: duration>),CRH :: GUI,std :: chrono :: duration>)>'_M_invoke(_Index_tuple <_Indices ...>)

可能会更清楚一点……但是对于GCC来说,它的要求太高了。

任何想法如何解决此问题?

#include <Types.hpp>
#include <thread>
#include <exception>
#include <functional>

class Thread
{
    private:

        std::exception_ptr exceptionPtr;
        std::thread thread;

    public:

        using Id = std::thread::id;

        using NativeHandleType = std::thread::native_handle_type;

        Thread() noexcept = default;
        Thread(Thread &&t) noexcept :
            exceptionPtr(std::move(t.exceptionPtr)),
            thread(std::move(t.thread))
        {
        }

        Thread &operator =(Thread &&t) noexcept
        {
            exceptionPtr = std::move(t.exceptionPtr);
            thread = std::move(t.thread);
            return *this;
        }

        template<typename Callable, typename... Args>
        Thread(Callable &&f, Args &&... args) :
            exceptionPtr(nullptr),
            thread([&](typename std::decay<Callable>::type &&f, typename std::decay<Args>::type &&... args)
            {
                try
                {
                    std::bind(f, args...)();
                }
                catch (...)
                {
                    exceptionPtr = std::current_exception();
                }

            }, std::forward<Callable>(f), std::forward<Args>(args)...)
        {
        }

        bool joinable() const noexcept
        {
            return thread.joinable();
        }

        void join()
        {
            thread.join();

            if (exceptionPtr != nullptr)
            {
                std::rethrow_exception(exceptionPtr);
            }
        }

        void detach()
        {
            thread.detach();
        }

        Id getId() const noexcept
        {
            return thread.get_id();
        }

        NativeHandleType nativeHandle()
        {
            return thread.native_handle();
        }

        static uint32_t hardwareConcurrency() noexcept
        {
            return std::thread::hardware_concurrency();
        }

        static void wait(Time t)
        {
            std::this_thread::sleep_for(t);
        }
};
皮特·斯科特尼克

Callable并且Args是转发引用,因此模板参数推导可以使它们成为左值引用或纯类型,具体取决于参数表达式的值类别。

这意味着当您在lambda的声明中重用推导的类型时:

thread([&](Callable&& f, Args&&... args)

引用折叠起作用,对于左值参数refreshDelay,它Args成为左值引用。

但是,std::thread存储接收到的参数的衰变副本,然后将其从其内部存储移至实际的处理程序,从而将存储的对象转换为xvalue。这就是错误告诉您的内容:处理程序无法与线程尝试传递的参数一起调用。

相反,您可以按以下方式实现它:

template <typename Callable, typename... Args>
Thread(Callable&& f, Args&&... args)
    : exceptionPtr(nullptr)
    , thread([] (typename std::decay<Callable>::type&& f
               , typename std::decay<Args>::type&&... args)
            {
                // (...)
            }
            , std::forward<Callable>(f), std::forward<Args>(args)...)
{
    // (...)
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

'std :: thread'如何确定传递给构造函数的可变参数的数量

如何将参数传递给Thread中的ThreadStart方法?

如何将可变参数传递给期望

如何将可变参数传递给观察者?

如何将可变参数传递给虚函数

函数的地址如何传递给 std::thread

如何将可变函数参数作为参数传递给另一个函数?

如何将可变参数函数的其余参数传递给另一个函数?

如何将可变参数传递给基于参数数量调用特定函数的函数?

将参数传递给std :: thread的区别,C ++

将参数传递给std :: thread包装器

如何将可变参数传递给具有继承关系的元素的向量?

如何将可变数量的参数传递给ant exec

如何将可变数量的参数传递给LLVM opt pass?

如何将可变参数传递给另一个函数

如何将可变数量的参数传递给lambda函数

是否可以以及如何将可变参数传递给Laravel中的中间件

如何将可变数量的参数传递给构造函数?

如何将可变列表传递给捆绑包?

如何将可变的自引用传递给特征方法?

如何将可变参量传递给其他功能

如何将可变数组结构传递给数组

如何将可变实体传递给泛型函数?

如何将可变内容传递给模态

PHP如何将可变长度函数参数传递给另一个可变长度函数?

将模板args传递给std :: thread

将参数传递给threading.Thread

将std :: sub_match作为参数传递给std :: thread时出了什么问题?

将可变参数模板参数传递给可变函数