Callable being required to be static in C++ class template

derkomai :

I would like to have the following class setup in a program:

  • A class that implements a buffer. This buffer, when full, would spawn a thread that makes a callback to handle what to do with the full buffer.
  • A base class template that includes a buffer object. Implements the callback function, which makes a call to a virtual function defined in a derived class.
  • A derived class that inherits from base class and implements what to do with the data.

First, the minimal reproducible example:

#include <vector>
#include <iostream>
#include <thread>

template <typename T>
class CallbackBuffer
{
    public:

        std::vector<T> buffer;
        void (*callback)(std::vector<T>);
        std::thread writerThread;

        CallbackBuffer(int bufferSize = 10)
        {
            buffer.resize(bufferSize);
        }

        void setCallback(void (*cb)(std::vector<T>))
        {
            callback = cb;
        }

        void writeCall()
        {
            writerThread = std::thread(callback, buffer);
        }
};

template <typename T>
class Base
{
    public:

        CallbackBuffer<T> buffer;

        Base()
        {
            buffer.setCallback(bufferHandler);
        }

        void bufferHandler(std::vector<T> v)
        {
            for(auto &i : v)
            {
                write(i);
            }
        }

        virtual void write(T i) = 0;
};

class Derived : public Base<int>
{
    public:

        Derived()
        {
        }

        void write(int i)
        {
            std::cout << i << std::endl;
        }
};

int main()
{
    Derived d;
    return 0;
}

I'm getting the following compiler error:

error: invalid use of non-static member function ‘void Base<T>::bufferHandler(std::vector<T>) [with T = int]’

So the compiler needs bufferHandler to be static, but if I did that, then I would not have access to the object's members. Is there a way to sort this, or just a horrible idea?

NutCracker :

You are passing the class member function so you need to have in your CallbackBuffer class something like:

void (Base<T>::*callback)(std::vector<T>);

// ...

void setCallback(void (Base<T>::*cb)(std::vector<T>)) {
    callback = cb;
}

and in Base class:

Base() {
    buffer.setCallback(&Base<T>::bufferHandler);
}

Demo

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=383608&siteId=1