模板化std::future返回的问题

Issue with a templated std::future return

本文关键字:返回 问题 future std      更新时间:2023-10-16

我使用c++ 11创建了一个线程池类,如下所示。

#include <iostream>
#include <functional>
#include <vector>
#include <condition_variable>
#include <thread>
#include <mutex>
#include <queue>
#include <atomic>
#include <future>
class threadpool {
    struct task {
        std::size_t m_priority;
        std::function<void()> m_fn;
        bool operator()(task* t1, task* t2) const {
            return t1->m_priority < t2->m_priority;
        }
    };
public:
    threadpool(std::size_t nthreads);
    ~threadpool();
    // void assign(std::function<void()> fn, std::size_t priority);
    template <typename T> std::future<T> assign(std::function<T()> fn, std::size_t priority);
private:
    void funnel();
    std::vector<std::thread*> m_threadlist;
    std::priority_queue<task*, std::vector<task*>, task> m_tasks;
    std::mutex m_tasks_mtx;
    std::condition_variable m_newc;
    std::mutex m_newc_mtx;
    std::atomic<bool> m_destruct;
};
threadpool::threadpool(std::size_t nthreads) {
    for (std::size_t _n = nthreads; _n > 0; --_n)
        m_threadlist.push_back(new std::thread(std::bind(&threadpool::funnel, this)));
}
threadpool::~threadpool() {
    m_destruct = true;
    while (!m_threadlist.empty()) {
        m_newc.notify_one();
    }
}
/* ... */
template <typename T>
std::future<T> assign(std::function<T()> fn, std::size_t priority) {
    std::promise<T> _prom;
    std::future<T> _ft = _prom.get_future();
    threadpool::task* _t = new task();
    _t->m_fn = std::bind([](std::promise<T>& p) {
        p.set_value(fn());
    }, std::ref(_prom));
    _t->m_priority = priority;
    {
        std::lock_guard<std::mutex> _lock(m_tasks_mtx);
        m_tasks.push(_t);
    }
    m_newc.notify_one();
    return _ft;
}
void threadpool::funnel() {
    while (!m_destruct) {
        {
            std::unique_lock<std::mutex> _lock(this->m_newc_mtx);
            m_newc.wait(_lock);
        }
        for (;;) {
            threadpool::task* _t;
            {
                std::lock_guard<std::mutex> _lock(m_tasks_mtx);
                if (m_tasks.empty()) break;
                _t = m_tasks.top();
                m_tasks.pop();
            }
            _t->m_fn();
            delete _t;
        }
    }
}
int count() {
    return 3;
}
int main(int argc, char* argv[])
{
    threadpool* herppool = new threadpool(10);
    for(int i = 0; i<900;i++) {
        auto derp = herppool->assign<int>(count,3); // <-- error here
        //printf("%d", derp.get());
    }
    delete herppool;
    //getchar();
}

我无法解决为什么在指定的行MSVC 2012下出现以下错误。

1>  main.cpp
1>main.obj : error LNK2001: unresolved external symbol "public: class std::future<int> __thiscall threadpool::assign<int>(class std::function<int __cdecl(void)>,unsigned int)" (??$assign@H@threadpool@@QAE?AV?$future@H@std@@V?$function@$$A6AHXZ@2@I@Z)
1>C:Users...visual studio 2012ProjectsthreadpoolReleasethreadpool.exe : fatal error LNK1120: 1 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

对我来说,这个函数是存在的。我不知道链接器在抱怨什么,非常感谢一些帮助跟踪错误。我已经盯着它看了好几个小时了

如果你仔细看这里:

template <typename T>
std::future<T> assign(std::function<T()> fn, std::size_t priority)

您不是定义threadpool::assign,而是定义一个名为assign的自由函数。链接器很清楚地告诉你,你忘记定义threadpool::assign了。你需要这样做:

template <typename T>
std::future<T> threadpool::assign(std::function<T()> fn, std::size_t priority)