1

有关使用 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 或更新的工作提案,并承认constexpr在 C++17 lambda 和其他边缘特性中仍然存在细微差别,这让我查找cppreference、 Josuttis 和其他人相当频繁。

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

4

2 回答 2

2

您的问题的答案在技术上是肯定的,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> );

活生生的例子

在这里,我制作了constant<x>创建std::integral_constant<X, x>. 这是一个无状态(但不是无价值!)类型,它有一个 constexpr 转换为其值。

我们可以将它传递给 lambda,只要 lambda 按值获取它,我们就可以将其转换为constexprlambda 中的值,包括将其作为模板非类型参数传递,实例化模板函数特化,如您所问为了。

可以在没有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") );

做正确的

于 2021-08-09T15:07:22.013 回答
0

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

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

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

template<int N>
void something();

constexpr int N = 10;

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

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

于 2021-08-09T14:48:52.683 回答