[英]Can I initialize an object's C style function pointer at compile time so that it calls the object's member function?
I'm writing a class to wrap around a library that requires callback function pointers.我正在编写一个 class 来包装一个需要回调 function 指针的库。 See below:
见下文:
struct LibraryConfig {
// Omitting other members...
void (*callback)(const char *);
};
class MyClass {
private:
LibraryConfig m_config;
public:
MyClass(const LibraryConfig &config) {
// Initialize m_config using config, would like to set callback so that it calls
// this->myCallback().
}
void myCallback(const char *);
};
Only static instances of MyClass will be declared, so construction can be kept within compile-time.只会声明 MyClass 的 static 实例,因此可以将构造保持在编译时间内。 I've tried lambdas and template functions that take MyClass pointers, but I either can't accomplish this within the constructor, or can't achieve this at compile-time (getting the address of an instance through
this
or &myClass
at compile-time doesn't seem possible).我已经尝试过接受 MyClass 指针的 lambdas 和模板函数,但我要么无法在构造函数中完成此操作,要么无法在编译时实现此操作(通过
this
或&myClass
在编译时获取实例的地址似乎不可能)。
constexpr
parameters may be allowed in the future, making this trivial to implement, but is there a way to accomplish this right now with C++20?将来可能会允许使用
constexpr
参数,这使得实现起来很简单,但是现在有没有办法用 C++20 来实现呢?
Yes, this is apparently possible.是的,这显然是可能的。 See the below snippet:
请参阅以下代码段:
struct LibraryConfig {
void (*callback)(const char *);
};
class MyClass {
private:
LibraryConfig config;
public:
consteval MyClass(const LibraryConfig& cfg) :
config(cfg) {}
void myCallback(const char *data);
};
int main()
{
constinit static MyClass mc = {{
[](const char *data) { mc.myCallback(data); }
}};
}
See a working example on Compiler Explorer here .在此处查看有关编译器资源管理器的工作示例。 Since
mc
is static, the lambda is allowed to access it without capture.由于
mc
是 static,因此允许 lambda 访问它而无需捕获。 There may be room for improvement on this solution, eg having the lambda be produced by a function.该解决方案可能还有改进的余地,例如让 lambda 由 function 生产。
Edit:编辑:
I've come up with a generalized function to create the lambda:我想出了一个通用的 function 来创建 lambda:
template<auto& inst, auto func>
consteval auto make_member_callback()
{
return []<typename... Args>(Args... args) { (inst.*func)(args...); };
}
This allows the following to be possible ( compiler explorer ):这允许以下操作成为可能(编译器资源管理器):
constinit static MyClass mc {{
make_member_callback<mc, &MyClass::myCallback>()
}};
Edit 2:编辑2:
Here is my final try at this, where the initialization is done within the class:这是我最后一次尝试,初始化在 class 中完成:
struct LibraryConfig {
void (*callback)(const char *);
};
template<auto& v, auto f>
constexpr auto member_callback = [](auto... args) { (v.*f)(args...); };
class MyClass {
private:
LibraryConfig config;
public:
consteval MyClass(const LibraryConfig& 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>());
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.