Я поделюсь с вами проблемой, которую я получил с классом, использующим параметры переменной функции. Это класс Thread, показанный в следующем коде. Это оболочка std :: thread для использования шаблона функции.
Я хотел использовать полиморфизм с этой функцией при наследовании класса Thread в новый класс Functor, но gcc возвращает следующие ошибки:
#include <thread>
#include <iostream>
using namespace std;
template<class... Args>
class Thread
{
public:
virtual void operator()(Args...) = 0;
void run(Args... args)
{
std::thread t(std::forward< Thread<Args...> >(*this), std::forward<Args>(args)...);
t.join();
}
};
template<class... Args>
class Functor : public Thread<Args...>
{
public:
// generates the errors bellow
virtual void operator()(Args... /*args*/)
{
}
// doesnot work since the pure virtual function wants another prototype of function.
// void operator()(int)
// {
// }
};
int main()
{
int a = 12;
Functor<int> f;
f.run(ref(a));
return 0;
}
из t-Thread-args2.cpp: 1: /usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/tuple: в реализации 'struct std :: _ Head_base ложь> ': /usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/tuple:215:12: требуется от 'struct std :: _ Tuple_impl, int> ' /usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/tuple:507:11: требуется из 'класса std :: tuple, int> ' /usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/functional:1601:39: требуется от 'struct std :: _ Bind_simple (интермедиат)>» /usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/thread:133:9: требуется от 'std: : поток :: поток (_Callable, _Args ...) [с _Callable = Thread; _Args = {int}] ’ t-Thread-args2.cpp: 14: 83: требуется от «void Thread :: run (Args ...) [with Args = {int}]» t-Thread-args2.cpp: 42: 17: требуется отсюда /usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/tuple:166:13: ошибка: невозможно объявить поле 'std :: _ Head_base, false> :: _ M_head_impl' будет иметь абстрактный тип 'Thread' t-Thread-args2.cpp: 7: 7: примечание: потому что следующие виртуальные функции являются чистыми внутри "Thread" t-Thread-args2.cpp: 10: 18: note: void Thread :: operator () (Args ...) [with Args = {int}]
Я не совсем понимаю ошибку, так как чисто виртуальная функция была хорошо определена в производном классе. Однако при перемещении функции run () в производный класс (Functor) это работает.
Заранее спасибо,
Джанер
В соответствии с [thread.thread.constr] §3, тип первого аргумента std::thread
конструктор F&&
с требованием, чтобы F
является MoveConstructible
, В твоем случае, F
является Thread
, который не MoveConstructible
,
Другими словами, std::thread
необходимо сохранить функтор по значению, и вы пересылаете функтор как Thread
, который является абстрактным.
Проблема в:
std::forward< Thread<Args...> >(*this)
который пытается скопировать Thread
субобъект. К счастью, он абстрактный, поэтому вы получаете ошибку компиляции, а не непредвиденное поведение во время выполнения.
Вы хотите ссылочную оболочку вместо:
std::ref(*this)
Я рассмотрел несколько советов, предоставленных участниками по этой теме, включая использование std::ref
и хотел бы поделиться с вами рабочей версией кода, решающей проблемы, возникшие с предыдущим кодом.
#include <thread>
#include <iostream>
using namespace std;
template<class... Args>
class Thread
{
public:
virtual void operator()(Args...) = 0;
void run(Args... args)
{
std::thread t(std::ref(*this), args...);
t.join();
}
};
template<class... Args>
class Functor : public Thread<Args...>
{
public:
void operator()(int)
{
while (1)
{
cout << "42 "; cout.flush();
}
}
};
int main()
{
int a = 12;
Functor<int> f;
f.run(ref(a));
return 0;
}
Еще раз спасибо.