lambda 可以实例化模板函数吗?

Can a lambda instantiate a template function?

关于使用 C++14 通用 lambda 或 C++20 模板 lambda 的问题通常是关于生成具有适当参数化类型的 lambda。

我的问题是,lambda 参数或其求值是否可能强制实例化(或专业化)模板,例如模板函数?参数 (n) 需要限定为 constexpr 才能工作。

template <int n> ret_type fn (...) {...}
...
auto fx = [] (int n) { return fn<n>(...) }

我并不完全了解 C++20 或更新的工作提案,并且承认在 C++17 lambda 和其他边缘功能中 constexpr 等仍然存在细微差别,这让我经常查找 cppreference、Josuttis 和其他人。

我知道这接近 XY 问题。由于模板实例化是在编译时执行的,因此模板参数的 lambda 表达式似乎是一种反模式。但是,如果类型和常量值在编译时已知,模板 可以 被实例化,是否有任何建议允许这种机制?

所问问题的答案是:是的,lambda 的主体可以实例化模板。

你问题中的具体例子是不可能的,因为函数参数不能是constexpr,这是用作模板参数所必需的。

您可以使用可从 lambda 定义的范围访问的 constexpr 变量:

template<int N>
void something();

constexpr int N = 10;

int main()
{
    auto f = [] { something<N>(); };
    f();
}

实例 here,其中 something 在 de lambda 表达式的主体内实例化。但我不认为那是你所追求的。请注意,调用 lambda 对象不会(而且永远不会导致)模板的实例化。

你的问题的答案在技术上是是的,lambda 体可以实例化模板函数。实际示例不起作用,因为不能以这种方式使用 int n 作为参数。

有一个简单的解决方法

template<auto x>
using constant_t = std::integral_constant< std::decay_t<decltype(x)>, x >;
template<auto x>
constexpr constant_t<x> constant = {};

template <int n> int fn () { int arr[n] = {0}; return sizeof(arr); }
auto fx = [] (auto n) { return fn<n>(); };
std::cout << fx( constant<3> );

Live example.

这里我创建了 constant<x> 变量模板来创建 std::integral_constant<X, x> 的实例。这是一种无状态(但不是无价值!)类型,它具有到其值的 constexpr 转换。

我们可以将其传递给 lambda,只要 lambda 按值获取它,我们就可以将其转换为 lambda 中的 constexpr 值,包括将其作为模板非类型参数传递, 根据您的要求实例化模板函数专业化。

可以在没有 constant 变量模板的情况下完成,即如果您没有 auto 参数支持:

template<std::size_t N>
using index_t = std::integral_constant<std::size_t, N>;
template<std::size_t N>
constexpr index_t<N> index = {};

我们可以使用它的特定类型版本,然后传递它,它的工作方式相同。


除此之外,constant<?> 很有趣。例如:

using upFILE=std::unique_ptr<
  std::FILE,
  constant_t<std::fclose>
>;

upFILE file( fopen("hello.txt", "r") );

做正确的事tm.