为什么 "this" 在编译时在 consteval 构造函数中未知?

Why isn't "this" known at compile time in a consteval constructor?

我正在编写一个 class 来包装与设备一起工作的基于 C 的库的一部分,其中每个设备都配置有回调函数指针来处理数据。将为每个设备创建一个 MyClass 实例。见下文:

struct DeviceConfig {
    void (*callback)(char *data);
};

class MyClass {
private:
    DeviceConfig config;

public:
    void myCallback(char *data);

    MyClass() {
        // Would like to set config.callback so that a call to it will result in a call of this->myCallback(data).
    }
};

由于无法将捕获的 lambda 转换为函数指针,我尝试了以下解决方法:

template<MyClass *MC>
auto binder() {
    return [](char *data) { MC->myCallback(data); };
}

MyClass::MyClass() {
    config.callback = binder<this>();
}

但是,编译器(最新的 GCC)不喜欢在构造函数中使用 binder,因为 this 在编译时不一定是已知的,尽管我知道MyClass 只会在编译时声明。

C++20 引入了 consteval 函数(和构造函数),其中 "must produce a compile-time constant."。但是,将 consteval 添加到构造函数 and/or binder 不会影响编译器的输出。 constexpr 也没有改变。

如果一个对象可以在编译时初始化,为什么不能在编译时也知道对象的 this?以上是否可以通过其他方式实现?

构造函数是函数,就像其他函数一样。与其他函数相比,它们的特权很少,其参数的常量表达式行为也不在其中。

this 本质上是所有非静态成员函数的参数。参数为 never constant expressions。因此,this 不能用在需要常量表达式的上下文中。如何创建 class 实例并不重要。你怎么称呼它并不重要。 constexpr/consteval 函数的参数永远不是常量表达式,包括 this.

接受的答案确实解释了为什么 this 不能在构造函数中使用;但是,我还询问是否有解决方法来实现我想要的。我找到了一个解决方法,并在另一个 Whosebug post .

中分享了该工作

为了节省点击次数,这是我的代码的最后一次迭代:

struct DeviceConfig {
    void (*callback)(const char *);
};

template<auto& v, auto f>
constexpr auto member_callback = [](auto... args) { (v.*f)(args...); };

class MyClass {
private:
    DeviceConfig config;

public:
    consteval MyClass(const DeviceConfig& cfg = {}) :
        config(cfg) {}

    template<MyClass& MC>
    constexpr static MyClass& init() {
        MC.config.callback = member_callback<MC, &MyClass::myCallback>;
        return MC;
    }

    void myCallback(const char *data);
};

int main()
{
    constinit static MyClass mc = (mc = MyClass(), MyClass::init<mc>());
}