繁体   English   中英

c++ 没有重载 function 的实例,但使用模板类型名...?

[英]c++ no instance of overloaded function, but using template typename…?

我试图从一本书中整理一些示例代码..但是这本书和 github 副本是不同的..我想我已经接近了一个线程池的工作示例,它接受函数并包装它们,所以你等待它们的价值作为未来返回......但在模板周围出现编译错误

我试图在helloworld.cpp的末尾实例化我需要的确切 class 就像在

为什么模板只能在 header 文件中实现?

但随后继续收到一堆关于试图暗示 function 的警告,我已经将其设置为=delete ...

看看我在为什么 C++11-deleted 函数参与重载解析下的意思?

我对 C++ 有点陌生,仍然不确定如何最好地继续,编译错误在最后。我已经测试过thread_safe_queue.cpp并且它已经在其他更简单的用法中工作,所以我不相信它在这里有问题。 ..更多所以模板需要帮助

你好世界.cpp

#include <thread>
#include <vector>
#include <atomic>
#include <iostream>
#include <future>
#include <functional>

#include <unistd.h>

 // https://github.com/anthonywilliams/ccia_code_samples/blob/6e7ae1d66dbd2e8f1ad18a5cf5c6d25a37b92388/listings/listing_9.1.cpp
 // https://github.com/anthonywilliams/ccia_code_samples/blob/6e7ae1d66dbd2e8f1ad18a5cf5c6d25a37b92388/listings/listing_9.2.cpp

#include "thread_safe_queue.cpp"

class function_wrapper
{
    struct impl_base {
        virtual void call()=0;
        virtual ~impl_base() {}
    };
    std::unique_ptr<impl_base> impl;
    template<typename F>
    struct impl_type: impl_base
    {
        F f;
        impl_type(F&& f_): f(std::move(f_)) {}
        void call() { f(); }
    };
public:
    template<typename F>
    function_wrapper(F&& f):
        impl(new impl_type<F>(std::move(f)))
    {}

    void call() { impl->call(); }

    function_wrapper(function_wrapper&& other):
        impl(std::move(other.impl))
    {}

    function_wrapper& operator=(function_wrapper&& other)
    {
        impl=std::move(other.impl);
        return *this;
    }

    function_wrapper(const function_wrapper&)=delete;
    function_wrapper(function_wrapper&)=delete;
    function_wrapper& operator=(const function_wrapper&)=delete;
};

struct join_threads
{
    join_threads(std::vector<std::thread>&)
    {}
};

class thread_pool
{
    std::atomic_bool done;
    thread_safe_queue<function_wrapper> work_queue;
    std::vector<std::thread> threads;
    join_threads joiner;

    void worker_thread()
    {
        while(!done)
        {
            std::function<void()> task;
            if(work_queue.try_pop(task))
            {
                task();
            }
            else
            {
                std::this_thread::yield();
            }
        }
    }
public:
    thread_pool():
        done(false),joiner(threads)
    {
        unsigned const thread_count=std::thread::hardware_concurrency();
        try
        {
            for(unsigned i=0;i<thread_count;++i)
            {
                threads.push_back(
                    std::thread(&thread_pool::worker_thread,this));
            }
        }
        catch(...)
        {
            done=true;
            throw;
        }
    }

    ~thread_pool()
    {
        done=true;
    }

    template<typename FunctionType>
    std::future<typename std::result_of<FunctionType()>::type>
    submit(FunctionType f)
    {
        typedef typename std::result_of<FunctionType()>::type result_type;
        
        std::packaged_task<result_type()> task(std::move(f));
        std::future<result_type> res(task.get_future());
        work_queue.push_back(std::move(task));
        return res;
    }
};

void find_the_answer_to_ltuae(){
    std::cout << "About to sleep 1 second...";
    sleep(1);
    std::cout<<"The answer is " << 42 << std::endl;
}

int main()
{
    std::cout << "About to create my_threadpool...." << std::endl;
    thread_pool my_threadpool;
    std::cout << "Done creating my_threadpool...." << std::endl;
    std::cout << "Submitting first job now" << std::endl;
    my_threadpool.submit(find_the_answer_to_ltuae);
    sleep(10);
    std::cout <<"Finished" << std::endl;
}

template class thread_safe_queue<function_wrapper>; // <-------- this was added by me, in an attempt to get the templating happy.. didn't work

线程安全队列.cpp

#include <mutex>
#include <memory>
#include <condition_variable>
#include <queue>

template <typename T>
class thread_safe_queue {
    public:
        // constructor
        thread_safe_queue() {}
        thread_safe_queue(const thread_safe_queue& other)
        {
            std::lock_guard<std::mutex> lock{other.mutex};
            queue = other.queue;
        }

        void push(T new_value)
        {
            std::lock_guard<std::mutex> lock{mutex};
            queue.push(new_value);
            cond.notify_one();
        }

        void wait_and_pop(T& value)
        {
            std::unique_lock<std::mutex> lock{mutex};
            cond.wait(lock, [this]{ return !queue.empty(); });
            value = queue.front();
            queue.pop();
        }

        std::shared_ptr<T> wait_and_pop()
        {
            std::unique_lock<std::mutex> lock{mutex};
            cond.wait(lock, [this]{ return !queue.empty(); });
            std::shared_ptr<T> res{std::make_shared<T>(queue.front())};
            queue.pop();
            return res;
        }

        bool try_pop(T& value)
        {
            std::lock_guard<std::mutex> lock{mutex};
            if (queue.empty())
                return false;
            value = queue.front();
            queue.pop();
            return true;
        }

        std::shared_ptr<T> try_pop()
        {
            std::lock_guard<std::mutex> lock{mutex};
            if (queue.empty())
                return std::shared_ptr<T>{};
            std::shared_ptr<std::mutex> res{std::make_shared<T>(queue.front())};
            queue.pop();
            return res;
        }

        bool empty() const
        {
            std::lock_guard<std::mutex> lock{mutex};
            return queue.empty();
        }

    private:
        mutable std::mutex mutex;
        std::condition_variable cond;
        std::queue<T> queue;
};


//https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file

没有模板 class function_wrapper .. 我的编译器给出

sh compile.sh                                       
-- Conan: Adjusting output directories
-- Conan: Using cmake targets configuration
-- Conan: Adjusting default RPATHs Conan policies
-- Conan: Adjusting language standard
-- Current conanbuildinfo.cmake directory: /build
-- Configuring done
-- Generating done
-- Build files have been written to: /build
Scanning dependencies of target test_cpp_multi
[ 33%] Building CXX object CMakeFiles/test_cpp_multi.dir/src/helloworld.cpp.o
/src/helloworld.cpp:70:27: error: no matching member function for call to 'try_pop'
            if(work_queue.try_pop(task))
               ~~~~~~~~~~~^~~~~~~
/src/thread_safe_queue.cpp:41:14: note: candidate function not viable: no known conversion from 'std::function<void ()>' to 'function_wrapper &' for 1st argument
        bool try_pop(T& value)
             ^
/src/thread_safe_queue.cpp:51:28: note: candidate function not viable: requires 0 arguments, but 1 was provided
        std::shared_ptr<T> try_pop()
                           ^
/src/helloworld.cpp:113:20: error: no member named 'push_back' in 'thread_safe_queue<function_wrapper>'
        work_queue.push_back(std::move(task));
        ~~~~~~~~~~ ^
2 errors generated.
make[2]: *** [CMakeFiles/test_cpp_multi.dir/src/helloworld.cpp.o] Error 1
make[1]: *** [CMakeFiles/test_cpp_multi.dir/all] Error 2
make: *** [all] Error 2

对于第一个错误

/src/helloworld.cpp:70:27: error: no matching member function for call to 'try_pop'
        if(work_queue.try_pop(task))
    

您的问题是该taskstd::function<void ()> ,但try_pop需要一个function_wrapper& std::function<void ()>没有operator function_wrapper& ,因此您不能将其传递给try_pop 您需要做的是将try_pop更改为采用const T& ,因此可以创建一个临时function_wrapper ,或者创建您自己的function_wrapper来包装task并将其传递给try_pop

你的第二个错误

/src/helloworld.cpp:113:20: error: no member named 'push_back' in 'thread_safe_queue<function_wrapper>'
    work_queue.push_back(std::move(task));
    

是一个错字。 您在 thread_safe_queue 中没有push_back thread_safe_queue ,但您确实有push function。 你只需要改变

work_queue.push_back(std::move(task));

work_queue.push(std::move(task));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM