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办法做到这一点.
有点。
这:
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'>- 然后我们以仍然不需要捕获的方式在函数模板体内重建字符串。
为了避免重复,这值得吗?或许。