【发布时间】:2023-03-25 02:45:01
【问题描述】:
我有一个与this one 有点相似的问题,但对于一个更有限的情况,我认为这应该是可能的:我想从多个 lambda 构造一个静态 constexpr 函数调用数组,每个 lambda 共享相同的签名.静态和 constexpr 部分在这里很重要,因为我在嵌入式系统上,我想确保这些表最终出现在 Flash 中。
所以基本上我想做的是
#include<vector>
#include<functional>
#include<variant>
using params_t = std::vector<std::variant<int, float /*maybe others*/ >>;
struct command_t {
using callable_t = std::function<void(params_t)>;
const callable_t func;
//other members..
};
class AClass {
template<typename func_t>
constexpr static command_t::callable_t make_callable(func_t fun) {
return [fun](params_t params){/*construct a call to fun using params and template magic*/};
}
static void mycommand();
static void mycommand2(int i);
//The following fails:
///"error: in-class initialization of static data member 'const command_t AClass::commands [2]' of non-literal type"
static constexpr command_t commands[2] = {command_t{make_callable(mycommand)},
command_t{make_callable(mycommand2)}};
};
请注意,这里的类型擦除非常有限,因为 lambda 的签名仅因捕获 fun 的签名而异。函数调用显然不需要(也不能)是 constexpr,只需构造。
所以基本上我的问题是我能否以某种方式制作commands 数组static constexpr,或者以某种方式使用std::function, 或inplace_function 之类的东西,或者可能通过旋转我自己的代码来对特定类型的lambda 进行类型擦除案例?
【问题讨论】:
-
没有捕获的Lambas可以转换为标准函数指针。这也意味着您可以摆脱不是 constexpr 的
std::function对象。所以你会有using callable_t = void (*)(params_t);。我不确定make_callable应该做什么。 -
@Darhuuk 请注意,lambda 确实有捕获。
make_callable实际上是一个模板:fun可以有任意数量和类型的参数,make_callable构造一个调用fun的 lambda,参数来自作为参数给出的变体向量(显然必须匹配fun的签名,在运行时检查)。 -
啊,我明白了。那么目标是“自动化”吗?因为在我看来,如果您手动写出每个 lambda,则无需捕获
fun(因为它们是静态函数)。 -
@Darhuuk 没错!
标签: c++ c++17 constexpr type-erasure std-function