为什么在 consteval 构造函数中编译时不知道“this”?

cly*_*yne 3 c++ c++20

我正在编写一个类来包装与设备一起使用的基于 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).
    }
};
Run Code Online (Sandbox Code Playgroud)

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

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

MyClass::MyClass() {
    config.callback = binder<this>();
}
Run Code Online (Sandbox Code Playgroud)

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

C++20 引入了“必须生成编译时常量”consteval的函数(和构造函数) 。。但是,添加到构造函数和/或不会影响编译器的输出。也不会改变事情。constevalbinderconstexpr

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

Nic*_*las 6

构造函数是函数,就像其他函数一样。与其他函数相比,它们几乎没有什么特殊特权,并且它们的参数的常量表达式行为也不是其中之一。

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

  • @NicolBolas:虽然要求对尚未做出的决定进行预测是不合适的,但询问扩展语言可能存在哪些技术障碍则不合适,而且可以具有教育意义。作为一个相关的例子,考虑到即使是“consteval”函数也必须有*一个*返回类型,这对于理解其参数缺乏常量表达式状态非常有帮助。 (2认同)