首页 文章

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

提问于
浏览
2

我正在与您分享我使用可变参数函数参数的类所遇到的问题 . 它是以下代码中显示的类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;
}
from t-Thread-args2.cpp:1:
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/tuple: In instantiation of ‘struct std::_Head_base, false>’:
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/tuple:215:12:   required from ‘struct std::_Tuple_impl, int>’
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/tuple:507:11:   required from ‘class std::tuple, int>’
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/functional:1601:39:   required from ‘struct std::_Bind_simple(int)>’
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/thread:133:9:   required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = Thread; _Args = {int}]’
t-Thread-args2.cpp:14:83:   required from ‘void Thread::run(Args ...) [with Args = {int}]’
t-Thread-args2.cpp:42:17:   required from here
/usr/lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/tuple:166:13: error: cannot declare field ‘std::_Head_base, false>::_M_head_impl’ to be of abstract type ‘Thread’
t-Thread-args2.cpp:7:7: note:   because the following virtual functions are pure within ‘Thread’:
t-Thread-args2.cpp:10:18: note:     void Thread::operator()(Args ...) [with Args = {int}]

我真的不理解错误,因为纯虚函数在派生类中得到了很好的定义 . 但是,在将函数run()移动到派生类(Functor)中时,它可以工作 .

提前谢谢,卡纳

3 回答

  • 1

    问题是:

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

    它试图复制 Thread 子对象 . 幸运的是它是抽象的,因此您得到编译错误而不是意外的运行时行为 .

    您想要一个引用包装器:

    std::ref(*this)
    
  • 2

    我考虑了参与者提供的多个建议,包括使用 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

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

    换句话说, std::thread 需要按值存储仿函数,并且您将仿函数转发为 Thread ,这是抽象的 .

相关问题