簡體   English   中英

在lambda內部傳遞參數時,無法調用成員指針

[英]Unable to call pointer-to-member when passing arguments inside lambda

我正在嘗試為std :: thread做一個包裝,使我可以查看正在調用的線程上引發了哪些異常。 加入線程后,我會將它們向上傳播。 當調用帶有參數的函數或不帶參數的類成員函數時,這可以很好地工作。 但是,如果我嘗試使其與接受參數的類成員函數一起使用,則會收到我難以理解的錯誤。 下面是一些示例代碼,可重現我所看到的問題。

#include <iostream>
#include <string>

#include <thread>
#include <exception>
#include <utility>

class BlazingThread {
public:
    template< typename Function, typename... Args >
    explicit BlazingThread( Function&& f, Args&&... args ){
        exception = nullptr;
        thread = std::thread(([&](){
            try{
                auto caller = std::forward<Function>(f);

                caller(args...);
            }catch(...){
                //non handled exception rethrow so we can stop whoever started this mess
                //exception = std::make_exception_ptr(BlazingException("An unknown error occurred!"));
            }

        }));

    }

    template< typename Function >
    explicit BlazingThread( Function&& f){
        exception = nullptr;
        thread = std::thread(([&](){
            try{
                //std::bind(f);
                std::forward<Function>(f);

            }catch(...){
                //non handled exception rethrow so we can stop whoever started this mess
            //  exception = std::make_exception_ptr(BlazingException("An unknown error occurred!"));
            }

        }));

    }

    BlazingThread(BlazingThread && other){
        this->thread = std::move(other.thread);
        this->exception = std::move(other.exception);
    }

    BlazingThread(){

    }

    BlazingThread& operator=(const BlazingThread&) = delete;
    BlazingThread& operator=(BlazingThread && other){
        this->thread = std::move(other.thread);
        this->exception = std::move(other.exception);
        return *this;
    }
    BlazingThread(const BlazingThread& other) = delete;
    virtual ~BlazingThread();

    void join();
    static unsigned int hardware_concurrency(){
        return std::thread::hardware_concurrency();
    }
private:
    std::thread thread;
    std::exception_ptr exception;
};





void BlazingThread::join(){
    thread.join();
    if(this->exception != nullptr){
        //an exception was thrown in the thread, lets rethrow it
        std::rethrow_exception(this->exception);
    }
}

BlazingThread::~BlazingThread() {
    // TODO Auto-generated destructor stub
}





void testFunction(int x, int y){
    int z = x + y;
    std::cout<<"x + y = "<<z<<std::endl;
    //throw BlazingException("A planned error!");
}

class TestClass{
public:
    TestClass(int newX){
        this->x = newX;
    }

    void talk(){
        std::cout<<"this is "<<x<<std::endl;
    }
    void talking(){

        BlazingThread thread2(&TestClass::talk);
        thread2.join();
        std::string msg = "something else ";
        BlazingThread thread3(&TestClass::talkSomething, msg);
        thread3.join();



    }

    void talkSomething(std::string testMsg){
        std::cout<<testMsg<<x<<std::endl;
    }
private:
    int x;
};

int main() {
    try{
        TestClass test(3);
        test.talk();

        BlazingThread thread(testFunction,2,4);

        thread.join();
    }catch(...){
        //std::cout<<"Found BlazingException, what = "<<e.what()<<std::endl;
    }
    return 0;
}

    BlazingThread thread3(&TestClass::talkSomething, msg);
    thread3.join();

防止編譯。 我看到的錯誤是

/usr/include/c++/5/functional: In instantiation of ‘struct std::_Bind_check_arity<void (TestClass::*)(std::__cxx11::basic_string<char>), std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>’:
    /usr/include/c++/5/functional:1439:12:   required from ‘struct std::_Bind_helper<false, void (TestClass::*)(std::__cxx11::basic_string<char>), std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>’
    /usr/include/c++/5/functional:1462:5:   required by substitution of ‘template<class _Func, class ... _BoundArgs> typename std::_Bind_helper<std::__is_socketlike<_Func>::value, _Func, _BoundArgs ...>::type std::bind(_Func&&, _BoundArgs&& ...) [with _Func = void (TestClass::*)(std::__cxx11::basic_string<char>); _BoundArgs = {std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&}]’
    ../src/simple-thread.cpp:24:34:   required from ‘BlazingThread::BlazingThread(Function&&, Args&& ...)::<lambda()> [with Function = void (TestClass::*)(std::__cxx11::basic_string<char>); Args = {std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&}]’
    ../src/simple-thread.cpp:24:80:   required from ‘struct BlazingThread::BlazingThread(Function&&, Args&& ...) [with Function = void (TestClass::*)(std::__cxx11::basic_string<char>); Args = {std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&}]::<lambda()>’
    ../src/simple-thread.cpp:21:10:   required from ‘BlazingThread::BlazingThread(Function&&, Args&& ...) [with Function = void (TestClass::*)(std::__cxx11::basic_string<char>); Args = {std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&}]’
    ../src/simple-thread.cpp:121:55:   required from here
    /usr/include/c++/5/functional:1426:7: error: static assertion failed: Wrong number of arguments for pointer-to-member
           static_assert(_Varargs::value
           ^

以下是我需要修復的工作版本,因此需要std :: ref來引用類似std :: thread的引用

    #include <iostream>
    #include <string>

    #include <thread>
    #include <exception>
    #include <utility>

    class BlazingThread {
    public:




        template< typename Function, typename... Args >
        explicit BlazingThread( Function&& f, Args&&... args ){
            exception = nullptr;

            thread = std::thread(([&f,args...](){
                try{
                    //auto caller = std::forward<Function>(f);

                    //caller(std::forward<Args>(args)...);
                    auto functionCall = std::bind(std::forward<Function>(f),args...);
                    functionCall();
                }catch(...){
                    //non handled exception rethrow so we can stop whoever started this mess
                    //exception = std::make_exception_ptr(BlazingException("An unknown error occurred!"));
                }

            }));

        }

        template< typename Function >
        explicit BlazingThread( Function&& f){
            exception = nullptr;
            thread = std::thread(([&](){
                try{
                    //std::bind(f);
                    std::forward<Function>(f)();

                }catch(...){
                    //non handled exception rethrow so we can stop whoever started this mess
                //  exception = std::make_exception_ptr(BlazingException("An unknown error occurred!"));
                }

            }));

        }

        BlazingThread(BlazingThread && other){
            this->thread = std::move(other.thread);
            this->exception = std::move(other.exception);
        }

        BlazingThread(){

        }

        BlazingThread& operator=(const BlazingThread&) = delete;
        BlazingThread& operator=(BlazingThread && other){
            this->thread = std::move(other.thread);
            this->exception = std::move(other.exception);
            return *this;
        }
        BlazingThread(const BlazingThread& other) = delete;
        virtual ~BlazingThread();

        void join();
        static unsigned int hardware_concurrency(){
            return std::thread::hardware_concurrency();
        }
    private:
        std::thread thread;
        std::exception_ptr exception;
    };





    void BlazingThread::join(){
        thread.join();
        if(this->exception != nullptr){
            //an exception was thrown in the thread, lets rethrow it
            std::rethrow_exception(this->exception);
        }
    }

    BlazingThread::~BlazingThread() {
        // TODO Auto-generated destructor stub
    }


    void testFunction(){
        std::cout<<"tester"<<std::endl;
        //throw BlazingException("A planned error!");
    }


    void testFunction2(int x, int y){
        int z = x + y;
        std::cout<<"x + y = "<<z<<std::endl;
        //throw BlazingException("A planned error!");
    }

    class TestClass{
    public:
        TestClass(int newX){
            this->x = newX;
        }

        void talk(){
            std::cout<<"this is "<<x<<std::endl;
        }
        void talking(){

            BlazingThread thread2(&TestClass::talk,this);
            thread2.join();
            std::string msg = "something else ";
            BlazingThread thread3(&TestClass::talkSomething,this, msg);
            thread3.join();



        }

        void talkSomething(std::string testMsg){
            std::cout<<testMsg<<x<<std::endl;
        }
    private:
        int x;
    };

    int main() {
        try{
            TestClass test(3);
            test.talking();

            BlazingThread thread(testFunction2,2,4);

            thread.join();
            BlazingThread thread2(testFunction);

            thread2.join();
        }catch(...){
            //std::cout<<"Found BlazingException, what = "<<e.what()<<std::endl;
        }
        return 0;
    }

更改

BlazingThread thread2(&TestClass::talk);

BlazingThread thread2(&TestClass::talk, this);

和類似的地方。 您需要傳遞該對象才能繼續工作。

當lambda超出當前作用域時,也請停止使用[&]捕獲(就像將其傳遞給std線程時一樣)。 但這只是運行時錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM