I would like to use my own Thread implementation by wrapping the std::thread class from C++11 so I will be able handle exceptions like I want.
Here is my wrap class:
#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);
        }
};
It works pretty well if there is no argument:
Thread([&]() {  /* do something */ }).detach();
... but if I try to pass variadic arguments:
Thread(&GUI::refreshTask, this, refreshDelay).detach();
... I get an error at compile time:
buildroot-2014.02/output/host/usr/i586-buildroot-linux-uclibc/include/c++/4.8.2/functional: In instantiation of '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: required from 'std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = CRH::Thread::Thread(Callable&&, Args&& ...) [with Callable = void (CRH::GUI::)(std::chrono::duration >); Args = {CRH::GUI const, std::chrono::duration >&}]::__lambda1; _Args = {void (CRH::GUI::&)(std::chrono::duration >), CRH::GUI const&, std::chrono::duration >&}]' /home/cyril/Documents/crh-2016/src/robot2/../core/Thread.hpp:72:30: required from '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: required from here buildroot-2014.02/output/host/usr/i586-buildroot-linux-uclibc/include/c++/4.8.2/functional:1697:61: error: no type named 'type' in 'class std::result_of)(std::chrono::duration >); 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: error: no type named 'type' in 'class std::result_of)(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...>)
It could be a little clearer... but it will be too demanding for GCC.
Any idea how to fix this issue?
Solution
#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);
        }
};
 
    