在 C++ class 模板中要求 Callable 是静态的

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

我想在程序中进行以下 class 设置:

首先,最小的可复制示例:

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

我收到以下编译器错误:

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

所以编译器需要 bufferHandler 是静态的,但如果我那样做,那么我将无法访问对象的成员。有没有办法对此进行排序,或者只是一个糟糕的想法?

您正在传递 class 成员函数,因此您需要在 CallbackBuffer class 中包含类似以下内容的内容:

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

// ...

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

并在 Base class:

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

Demo

成员函数指针的类型与常规函数不同,这就是您的代码无法运行的原因。您可能想要的是使用 std::function 而不是原始指针:

#include <functional>

//...
std::function<void(std::vector<T>)> callback;

// ...

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

然后这样传递:

Base() {
    buffer.setCallback([this](auto& vec){ this->bufferHandler(vec); });
}

恕我直言,这比传递成员指针更具可读性和灵活性