使用纯虚拟类创建boost线程

时间:2014-11-04 19:31:35

标签: c++ multithreading boost g++ this

我正在尝试使用实现operator()的回调类创建一个线程。该类包含一个纯虚方法。回调使用虚函数进行处理。这是一个封装了这个想法并抛出一些编译器错误的示例:

#include <boost/chrono.hpp>
#include <boost/thread.hpp>
#include <iostream>

class Test {
    protected:
        int x;
    public:
        Test(void): x(10) {};
        virtual void operator()(void);
        boost::thread run(void);
        virtual void a(void) = 0;
};

void Test::operator()(void) {
    this->a();
    x += 10;
    std::cout << "Current Value:" << x << std::endl;
}

boost::thread Test::run(void) {
    return boost::thread(*this);
}

class Test1 : public Test {
    public:
        virtual void a(void);
};

void Test1::a(void) {
    x--;
}

main() {
    Test1 test = Test1();
    test.run().join();
}

我在Arch Linux上使用 gcc(GCC)4.9.1 20140903(预发行版)。运行g++ test.cpp -lboost_thread -lboost_system时出现以下编译器错误:

test.cpp: In member function ‘boost::thread Test::run()’:
test.cpp:22:31: error: no matching function for call to ‘boost::thread::thread(Test&)’
     return boost::thread(*this);
                               ^
test.cpp:22:31: note: candidates are:
In file included from /usr/include/boost/thread/thread_only.hpp:22:0,
                 from /usr/include/boost/thread/thread.hpp:12,
                 from /usr/include/boost/thread.hpp:13,
                 from test.cpp:2:
/usr/include/boost/thread/detail/thread.hpp:441:9: note: template<class F, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8, class A9> boost::thread::thread(F, A1, A2, A3, A4, A5, A6, A7, A8, A9)
         thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8,A9 a9):
         ^
/usr/include/boost/thread/detail/thread.hpp:441:9: note:   template argument deduction/substitution failed:
test.cpp:22:31: note:   candidate expects 10 arguments, 1 provided
     return boost::thread(*this);
                               ^
In file included from /usr/include/boost/thread/thread_only.hpp:22:0,
                 from /usr/include/boost/thread/thread.hpp:12,
                 from /usr/include/boost/thread.hpp:13,
                 from test.cpp:2:
/usr/include/boost/thread/detail/thread.hpp:434:9: note: template<class F, class A1, class A2, class A3, class A4, class A5, class A6, class A7, class A8> boost::thread::thread(F, A1, A2, A3, A4, A5, A6, A7, A8)
         thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7,A8 a8):
         ^
/usr/include/boost/thread/detail/thread.hpp:434:9: note:   template argument deduction/substitution failed:
test.cpp:22:31: note:   candidate expects 9 arguments, 1 provided
     return boost::thread(*this);
                               ^
In file included from /usr/include/boost/thread/thread_only.hpp:22:0,
                 from /usr/include/boost/thread/thread.hpp:12,
                 from /usr/include/boost/thread.hpp:13,
                 from test.cpp:2:
/usr/include/boost/thread/detail/thread.hpp:427:9: note: template<class F, class A1, class A2, class A3, class A4, class A5, class A6, class A7> boost::thread::thread(F, A1, A2, A3, A4, A5, A6, A7)
         thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6,A7 a7):
         ^
/usr/include/boost/thread/detail/thread.hpp:427:9: note:   template argument deduction/substitution failed:
test.cpp:22:31: note:   candidate expects 8 arguments, 1 provided
     return boost::thread(*this);
                               ^
In file included from /usr/include/boost/thread/thread_only.hpp:22:0,
                 from /usr/include/boost/thread/thread.hpp:12,
                 from /usr/include/boost/thread.hpp:13,
                 from test.cpp:2:
/usr/include/boost/thread/detail/thread.hpp:420:9: note: template<class F, class A1, class A2, class A3, class A4, class A5, class A6> boost::thread::thread(F, A1, A2, A3, A4, A5, A6)
         thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5,A6 a6):
         ^
/usr/include/boost/thread/detail/thread.hpp:420:9: note:   template argument deduction/substitution failed:
test.cpp:22:31: note:   candidate expects 7 arguments, 1 provided
     return boost::thread(*this);
                               ^
In file included from /usr/include/boost/thread/thread_only.hpp:22:0,
                 from /usr/include/boost/thread/thread.hpp:12,
                 from /usr/include/boost/thread.hpp:13,
                 from test.cpp:2:
/usr/include/boost/thread/detail/thread.hpp:413:9: note: template<class F, class A1, class A2, class A3, class A4, class A5> boost::thread::thread(F, A1, A2, A3, A4, A5)
         thread(F f,A1 a1,A2 a2,A3 a3,A4 a4,A5 a5):
         ^
/usr/include/boost/thread/detail/thread.hpp:413:9: note:   template argument deduction/substitution failed:
test.cpp:22:31: note:   candidate expects 6 arguments, 1 provided
     return boost::thread(*this);
                               ^
In file included from /usr/include/boost/thread/thread_only.hpp:22:0,
                 from /usr/include/boost/thread/thread.hpp:12,
                 from /usr/include/boost/thread.hpp:13,
                 from test.cpp:2:
/usr/include/boost/thread/detail/thread.hpp:406:9: note: template<class F, class A1, class A2, class A3, class A4> boost::thread::thread(F, A1, A2, A3, A4)
         thread(F f,A1 a1,A2 a2,A3 a3,A4 a4):
         ^
/usr/include/boost/thread/detail/thread.hpp:406:9: note:   template argument deduction/substitution failed:
test.cpp:22:31: note:   candidate expects 5 arguments, 1 provided
     return boost::thread(*this);
                               ^
In file included from /usr/include/boost/thread/thread_only.hpp:22:0,
                 from /usr/include/boost/thread/thread.hpp:12,
                 from /usr/include/boost/thread.hpp:13,
                 from test.cpp:2:
/usr/include/boost/thread/detail/thread.hpp:399:9: note: template<class F, class A1, class A2, class A3> boost::thread::thread(F, A1, A2, A3)
         thread(F f,A1 a1,A2 a2,A3 a3):
         ^
/usr/include/boost/thread/detail/thread.hpp:399:9: note:   template argument deduction/substitution failed:
test.cpp:22:31: note:   candidate expects 4 arguments, 1 provided
     return boost::thread(*this);
                               ^
In file included from /usr/include/boost/thread/thread_only.hpp:22:0,
                 from /usr/include/boost/thread/thread.hpp:12,
                 from /usr/include/boost/thread.hpp:13,
                 from test.cpp:2:
/usr/include/boost/thread/detail/thread.hpp:392:9: note: template<class F, class A1, class A2> boost::thread::thread(F, A1, A2)
         thread(F f,A1 a1,A2 a2):
         ^
/usr/include/boost/thread/detail/thread.hpp:392:9: note:   template argument deduction/substitution failed:
test.cpp:22:31: note:   candidate expects 3 arguments, 1 provided
     return boost::thread(*this);
                               ^
In file included from /usr/include/boost/thread/thread_only.hpp:22:0,
                 from /usr/include/boost/thread/thread.hpp:12,
                 from /usr/include/boost/thread.hpp:13,
                 from test.cpp:2:
/usr/include/boost/thread/detail/thread.hpp:386:9: note: template<class F, class A1> boost::thread::thread(F, A1, typename boost::disable_if<boost::thread_detail::is_convertible<F&, boost::thread_attributes>, boost::thread::dummy*>::type)
         thread(F f,A1 a1,typename disable_if<boost::thread_detail::is_convertible<F&,thread_attributes >, dummy* >::type=0):
         ^
/usr/include/boost/thread/detail/thread.hpp:386:9: note:   template argument deduction/substitution failed:
test.cpp:22:31: note:   candidate expects 3 arguments, 1 provided
     return boost::thread(*this);
                               ^
In file included from /usr/include/boost/thread/thread_only.hpp:22:0,
                 from /usr/include/boost/thread/thread.hpp:12,
                 from /usr/include/boost/thread.hpp:13,
                 from test.cpp:2:
/usr/include/boost/thread/detail/thread.hpp:335:9: note: boost::thread::thread(boost::detail::thread_move_t<boost::thread>)
         thread(BOOST_THREAD_RV_REF(thread) x) BOOST_NOEXCEPT
         ^
/usr/include/boost/thread/detail/thread.hpp:335:9: note:   no known conversion for argument 1 from ‘Test’ to ‘boost::detail::thread_move_t<boost::thread>’
/usr/include/boost/thread/detail/thread.hpp:325:9: note: template<class F> boost::thread::thread(const attributes&, boost::detail::thread_move_t<T>)
         thread(attributes const& attrs, BOOST_THREAD_RV_REF(F) f):
         ^
/usr/include/boost/thread/detail/thread.hpp:325:9: note:   template argument deduction/substitution failed:
test.cpp:22:31: note:   cannot convert ‘*(Test*)this’ (type ‘Test’) to type ‘const attributes& {aka const boost::thread_attributes&}’
     return boost::thread(*this);
                               ^
In file included from /usr/include/boost/thread/thread_only.hpp:22:0,
                 from /usr/include/boost/thread/thread.hpp:12,
                 from /usr/include/boost/thread.hpp:13,
                 from test.cpp:2:
/usr/include/boost/thread/detail/thread.hpp:312:18: note: template<class F> boost::thread::thread(boost::detail::thread_move_t<T>, typename boost::disable_if<boost::is_same<typename boost::decay<F>::type, boost::thread>, boost::thread::dummy*>::type)
         explicit thread(BOOST_THREAD_RV_REF(F) f
                  ^
/usr/include/boost/thread/detail/thread.hpp:312:18: note:   template argument deduction/substitution failed:
test.cpp:22:31: note:   ‘Test’ is not derived from ‘boost::detail::thread_move_t<T>’
     return boost::thread(*this);
                               ^
In file included from /usr/include/boost/thread/thread_only.hpp:22:0,
                 from /usr/include/boost/thread/thread.hpp:12,
                 from /usr/include/boost/thread.hpp:13,
                 from test.cpp:2:
/usr/include/boost/thread/detail/thread.hpp:303:9: note: template<class F> boost::thread::thread(const attributes&, F, typename boost::disable_if<boost::thread_detail::is_convertible<F&, boost::detail::thread_move_t<T> >, boost::thread::dummy*>::type)
         thread(attributes const& attrs, F f
         ^
/usr/include/boost/thread/detail/thread.hpp:303:9: note:   template argument deduction/substitution failed:
test.cpp:22:31: note:   cannot convert ‘*(Test*)this’ (type ‘Test’) to type ‘const attributes& {aka const boost::thread_attributes&}’
     return boost::thread(*this);
                               ^
In file included from /usr/include/boost/thread/thread_only.hpp:22:0,
                 from /usr/include/boost/thread/thread.hpp:12,
                 from /usr/include/boost/thread.hpp:13,
                 from test.cpp:2:
/usr/include/boost/thread/detail/thread.hpp:292:18: note: template<class F> boost::thread::thread(F, typename boost::disable_if_c<boost::thread_detail::is_convertible<F&, boost::detail::thread_move_t<T> >::value, boost::thread::dummy*>::type)
         explicit thread(F f
                  ^
/usr/include/boost/thread/detail/thread.hpp:292:18: note:   template argument deduction/substitution failed:
/usr/include/boost/thread/detail/thread.hpp: In substitution of ‘template<class F> boost::thread::thread(F, typename boost::disable_if_c<boost::thread_detail::is_convertible<F&, boost::detail::thread_move_t<T> >::value, boost::thread::dummy*>::type) [with F = Test]’:
test.cpp:22:31:   required from here
/usr/include/boost/thread/detail/thread.hpp:292:18: error: invalid abstract parameter type ‘Test’
test.cpp:5:7: note:   because the following virtual functions are pure within ‘Test’:
 class Test {
       ^
test.cpp:12:22: note:   virtual void Test::a()
         virtual void a(void) = 0;
                      ^
In file included from /usr/include/boost/thread/thread_only.hpp:22:0,
                 from /usr/include/boost/thread/thread.hpp:12,
                 from /usr/include/boost/thread.hpp:13,
                 from test.cpp:2:
/usr/include/boost/thread/detail/thread.hpp:244:9: note: boost::thread::thread()
         thread() BOOST_NOEXCEPT;
         ^
/usr/include/boost/thread/detail/thread.hpp:244:9: note:   candidate expects 0 arguments, 1 provided
In file included from /usr/include/boost/thread/thread_only.hpp:22:0,
                 from /usr/include/boost/thread/thread.hpp:12,
                 from /usr/include/boost/thread.hpp:13,
                 from test.cpp:2:
/usr/include/boost/thread/detail/thread.hpp:191:18: note: boost::thread::thread(boost::detail::thread_data_ptr)
         explicit thread(detail::thread_data_ptr data);
                  ^
/usr/include/boost/thread/detail/thread.hpp:191:18: note:   no known conversion for argument 1 from ‘Test’ to ‘boost::detail::thread_data_ptr {aka boost::shared_ptr<boost::detail::thread_data_base>}’
In file included from /usr/include/boost/thread/lock_guard.hpp:11:0,
                 from /usr/include/boost/thread/pthread/thread_data.hpp:11,
                 from /usr/include/boost/thread/thread_only.hpp:17,
                 from /usr/include/boost/thread/thread.hpp:12,
                 from /usr/include/boost/thread.hpp:13,
                 from test.cpp:2:
/usr/include/boost/thread/detail/thread.hpp:163:7: note: boost::thread::thread(boost::thread&)
       BOOST_THREAD_MOVABLE_ONLY(thread)
       ^
/usr/include/boost/thread/detail/thread.hpp:163:7: note:   no known conversion for argument 1 from ‘Test’ to ‘boost::thread&’

当类具有纯虚方法时,似乎使用*this作为仿函数存在问题。

  1. 概念上导致错误的原因是什么?
  2. 如何以编译的方式实现此代码段中的功能?
  3. 顺便说一下,该程序的预期输出为Current Value:19

2 个答案:

答案 0 :(得分:2)

从概念上讲,问题是你正在尝试创建一个Test对象 - 这是不可能的,因为它有一个纯虚函数。你的相关编译错误隐藏在某处:

/usr/include/boost/thread/detail/thread.hpp:292:18: note:   template argument deduction/substitution failed:
/usr/include/boost/thread/detail/thread.hpp: In substitution of ‘template<class F> boost::thread::thread(F, typename boost::disable_if_c<boost::thread_detail::is_convertible<F&, boost::detail::thread_move_t<T> >::value, boost::thread::dummy*>::type) [with F = Test]’:
test.cpp:22:31:   required from here
/usr/include/boost/thread/detail/thread.hpp:292:18: error: invalid abstract parameter type ‘Test’
test.cpp:5:7: note:   because the following virtual functions are pure within ‘Test’:
 class Test {
       ^

你需要给boost::thread一些实际上可构造的东西。最简单的只是一个lambda:

boost::thread Test::run(void) {
    return boost::thread([this]{
        this->operator();
    });
}

[更新]或实际上更简单:

boost::thread Test::run(void) {
    return boost::thread(&Test::operator(), this);
}

答案 1 :(得分:1)

boost::thread构造函数要求参数为Copyable,并按值(如果它不是rvalue)获取。所以你希望编译器创建一个抽象的Test实例,它并不同意:

error: invalid abstract parameter type ‘Test’