C ++ полиморфизм с параметром переменной функции

Я поделюсь с вами проблемой, которую я получил с классом, использующим параметры переменной функции. Это класс 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) это работает.

Заранее спасибо,
Джанер

2

Решение

В соответствии с [thread.thread.constr] §3, тип первого аргумента std::thread конструктор F&&с требованием, чтобы F является MoveConstructible, В твоем случае, F является Thread, который не MoveConstructible,

Другими словами, std::thread необходимо сохранить функтор по значению, и вы пересылаете функтор как Thread, который является абстрактным.

2

Другие решения

Проблема в:

std::forward< Thread<Args...> >(*this)

который пытается скопировать Thread субобъект. К счастью, он абстрактный, поэтому вы получаете ошибку компиляции, а не непредвиденное поведение во время выполнения.

Вы хотите ссылочную оболочку вместо:

std::ref(*this)
1

Я рассмотрел несколько советов, предоставленных участниками по этой теме, включая использование 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;
}

Еще раз спасибо.

1
По вопросам рекламы [email protected]