【发布时间】:2021-04-28 16:41:47
【问题描述】:
我正在尝试将 lambda(通过引用捕获本地上下文)传递给函数并确保它是内联的。 我认为一个解决方案是使用函数模板和 C++20 概念,但我不知道如何编写采用特定类型的 lambda 概念。
目的是分解光栅文件上的复杂循环,并让调用者为每个像素执行代码。
必须内联 lambda 调用。
我运气不好:
-
std::function:使用 lambda 的性能比在调用者代码中编写整个循环差 2 倍。 - 函数指针:带捕获(this 或局部变量)的 lambda 无法转换为函数指针
- 模板方法:我不能重载它,也不能像以前的解决方案那样容易地检查 lambda 类型。
性能不佳的工作代码:
// loop
template<typename T>
class Raster<T>
{
template<typename FileDataType>
void SaveToDisk(std::ostream& file, const std::function<FileDataType(T&)>& callback) const;
template<typename FileDataType>
void SaveToDisk(std::ostream& file, AnotherCallbackType...);
}
// call
class GeoRaster<double> : public Raster
{
void Test()
{
// Creates a file containing "short" values, from a GeoRaster<double>
SaveToDisk<short>(file, [&](double val)
{
// this lambda call must be inlined
if (val == this->nodata)
{
return 255;
}
else
{
return short(val) / 16;
}
}
}
});
你能帮我写一个这样的概念吗:
template<typename T, typename FileDataType>
concept SimpleWriteCallback = requires(T a) {
{ a } -> std::convertible_to<std::function<FileDataType(T&)>>;
};
template<typename FileDataType, SimpleWriteCallback<FileDataType> Callback>
void SaveToDisk(std::ostream& file, Callback& callback) const;
【问题讨论】:
-
为什么
std::function?您需要可以使用给定参数调用的东西,而不是std::function。 -
"确保它是内联的" 你为什么在乎?为什么函数是否声明为
inline是你的事?此外,至少就 C++ 标准而言,无法确保 anything 是“内联”的。 -
强制内联将需要编译器特定的方法来执行此操作,因为这不是标准正式涵盖的内容。对于 MSVC,您可以在较新的编译器版本中使用 (IIRC) lambda 上的
[[msvc::forceinline]]属性(因为__forceinline不起作用)。对于 GCC/Clang,__attribute__((always_inline))适用于 lambdas IIRC,但[[gnu::always_inline]]不适用 -
我只需要它非常高效。这个问题可以改写为:我可以将循环和单次迭代逻辑分开并保持相同的性能水平吗?如果是这样:如何?我需要适当优化循环,但由于程序中有很多次相同类型的代码,我想将其分解。
-
function_view你可能会感兴趣。
标签: c++ templates lambda c++20 c++-concepts