具有可变函数参数的C++多态性

C++ polymorphism with variadic function parameter

本文关键字:C++ 多态性 参数 函数      更新时间:2023-10-16

我将与您分享一个使用变函数参数的类的问题。它是以下代码中显示的类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,false>"的实例化中://usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../include/c++/4.7.2/元组: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:"class 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(int)>'中必需//usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../include/c++/4.7.2/thread:133:9:必需自"std::thread::thread(_Callable&&,_Args&&…)[with_Callable=thread;_Args={int}]"t-Thread-args2.cpp:14:83:"void Thread::run(Args…)[with Args={int}]"中需要t线程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:注意:因为以下虚拟函数在"线程"中是纯函数:t-Thread-args2.cpp:10:18:注意:void线程::operator()(Args…)[带有Args={int}]

我真的不理解这个错误,因为纯虚拟函数在被嘲笑的类中定义得很好。然而,在将函数run()移动到派生类(Functor)中时,它是有效的。

提前感谢,Caner

根据[thread.thread.contr]§3,std::thread构造函数的第一个参数类型为F&&,要求FMoveConstructible。在您的情况下,FThread,而不是MoveConstructible

换句话说,std::thread需要按值存储函子,而您将函子转发为Thread,这是抽象的。

问题是:

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

其试图复制CCD_ 10子对象。幸运的是,它是抽象的,所以您会得到编译错误,而不是意外的运行时行为。

您需要一个引用包装器:

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;
}

再次感谢。