constexpr参数化函数指针

Prz*_*ski 7 c++ lambda constexpr c++17

我有以下第三方API:

using StatisticsFunc = double (*)(const std::vector<double> &)
libraryClass::ComputeStatistics(StatisticsFunc sf);
Run Code Online (Sandbox Code Playgroud)

我正在使用这样的:

obj1->ComputeStatistics([](const auto& v) {return histogram("obj1", v);};
obj2->ComputeStatistics([](const auto& v) {return histogram("obj2", v);};
Run Code Online (Sandbox Code Playgroud)

但所有这些lambdas只是重复代码.我宁愿这样:

obj1->ComputeStatistics(getHistogramLambda("obj1"));
Run Code Online (Sandbox Code Playgroud)

所以我需要定义:

constexpr auto getHistogramLambda(const char* name) {
    return [](const auto& v) {return histogram(name, v);};
}
Run Code Online (Sandbox Code Playgroud)

但它不起作用,因为name没有被捕获.这也不会起作用:

constexpr auto getHistogramLambda(const char* name) {
    return [name](const auto& v) {return histogram(name, v);};
}
Run Code Online (Sandbox Code Playgroud)

因为捕获lambda不再是无状态的,不能转换为函数指针.

Ofc可以将其作为宏来实现,但我想要一个现代的C++ 17解决方案.

传递字符串作为模板参数似乎也是一个选项:https: //stackoverflow.com/a/28209546/7432927,但我很好奇是否有constexpr办法做到这一点.

Bar*_*rry 3

有点。

这:

obj1->ComputeStatistics(getHistogramLambda("obj1"));
Run Code Online (Sandbox Code Playgroud)

由于您指出的原因不起作用 - 您需要捕获状态。然后,我们不能这样写:

obj1->ComputeStatistics(getHistogramLambda<"obj1">());
Run Code Online (Sandbox Code Playgroud)

因为虽然我们可以拥有类型的模板参数,但const char*我们不能将它们绑定到字符串文字。你可以这样做:

template <const char* name>
constexpr auto getHistogramLambda() {
    return [](const auto& v) {return histogram(name, v);};
}

const char p[] = "obj1";
obj1->ComputeStatistics(getHistogramLambda<p>());
Run Code Online (Sandbox Code Playgroud)

这非常尴尬,因为您需要为每次调用引入额外的变量。在 C++20 中,我们将能够编写一个以固定字符串作为模板参数的类类型,这将允许getHistogramLambda<"obj1">工作,只是方式略有不同。

在那之前,目前最好的方法可能是使用 UDL 来捕获单个字符作为某些类类型的模板参数:

template <char... Cs>
constexpr auto getHistogramLambda(X<Cs...>) {
    static constexpr char name[] = {Cs..., '\0'};
    return [](const auto& v) { return histogram(name, v);};
}


obj->ComputeStatistic(getHistogramLambda("obj1"_udl));
Run Code Online (Sandbox Code Playgroud)

这里的意图是这"obj"_udl是一个类型的对象X<'o', 'b', 'j', '1'>- 然后我们以仍然不需要捕获的方式在函数模板体内重建字符串。

为了避免重复,这值得吗?或许。