2014-11-04 3 views
-1

Я пытаюсь создать поток с классом обратного вызова, реализующим operator(). Класс содержит чистый виртуальный метод. Обратный вызов использует виртуальную функцию для выполнения своей обработки. Вот пример, который инкапсулирует идею и бросает некоторые ошибки компилятора:Создание потока boost с чистым виртуальным классом

#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(); 
} 

Я использую GCC (GCC) 4.9.1 20140903() предварительную версию на Arch Linux. Я получаю следующие ошибки компиляции при запуске 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. Как можно реализовать функциональные возможности этого фрагмента таким образом, чтобы он компилировался?

Кстати, ожидаемый выход программы - Current Value:19.

ответ

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 то, что на самом деле конструктивна. Проще всего лямбда:

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

[обновление] или на самом деле проще:

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

Я не использую C++ 11. Я рассматриваю два варианта ATM: либо переходя в 'boost :: ref (this)', либо помещая 'operator()' во вложенную структуру и передавая это. Оба они примерно эквивалентны лямбда, хотя последнее, вероятно, предпочтительнее так как это можно сделать безопаснее. Есть предположения? –

+0

Можете ли вы просто выполнить boost :: thread (& Test :: operator(), this) '? – Barry

+0

LOL благодарит за изменение, что было немым. – Barry

1

boost::thread Конструктор требует, чтобы аргумент был пригодным для копирования, и принимает его по значению (если это не значение rvalue). Таким образом, вы хотите, чтобы компилятор создать экземпляр Test, который является абстрактным, и он не согласен:

error: invalid abstract parameter type ‘Test’ 
+0

Это имеет смысл. Как это исправить? –

Смежные вопросы