从 lambda 中推导模板参数
Template argument deduction from lambda
我正在尝试编写一个函数,该函数基本上将一种类型模板化的类的实例转换为另一种类型上模板化的同一类的实例。我想避免在调用函数时显式声明模板类型。
这是我正在尝试执行的操作的最小可编译示例:
template<class T> class container {};
template <class A, class B, template <class C> class Container>
Container<B> transform(Container<A> c, B(func)(A))
{
return Container<B>{};
}
int do_something(int in)
{
return in + 1;
}
int main()
{
container<int> c{};
//this one doesn't work:
//transform(c, [](int in) -> int { return in + 1; });
//these are fine:
transform<int, int>(c, [](int in) -> int { return in + 1; });
transform(c, do_something);
return 0;
}
取消注释掉第一个transform
调用会导致编译错误:
Visual Studio 2017:
error C2784: 'Container<B> transform(Container<A>,B (__cdecl *)(A))': could not deduce template argument for 'B (__cdecl *)(A)' from 'test::<lambda_afc081691b59f849887abca17e74b763>'
无论 coliru.stacked-crooked.com 默认使用哪个版本的 g++:
main.cpp:4:14: note: template argument deduction/substitution failed:
main.cpp:18:52: note: mismatched types 'B (*)(A)' and 'main()::<lambda(int)>'
transform(c, [](int in) -> int { return in + 1; });
^
这是否意味着编译器不可能推断出lambda的签名,即使它已经像这样明确定义?
我知道我可以像这样重写我的转换函数:
template <class A, template <class C> class Container, class F>
auto transform(Container<A> c, F func)->Container<decltype(func(A{}))>
{
return Container<decltype(func(A{}))>{};
}
但是现在函数签名的可读性有点差,如果我提供不合适的函数,我收到的错误消息非常不友好。使用std::function<B(A)>
也无济于事。
有没有办法将更严格指定的函数参数与 lambda 一起使用,而无需显式添加模板类型?
您需要将无捕获的 lambda 转换为执行操作的静态函数。实际上,通过应用一元+
运算符可以相当容易地调用该转换。
transform(c, +[](int in) -> int { return in + 1; });
由于无捕获lambda的闭包类型有一个转换运算符要ret(*)(params)
,编译器在遇到+
时会调用它。这是因为您实际上可以将+
应用于指针类型。
[expr.unary.op/7]
一元 + 运算符的操作数应具有算术、无作用域枚举或指针类型,结果是参数的值。整型提升对整型或枚举操作数执行。结果的类型是升级的操作数的类型。
B
和A
不能从lambda中B(func)(A)
推断出来。
您可以将模板更改为更通用,例如:
template <template <typename...> class Container, typename Ts...>
auto transform(const Container<Ts...>& c, F f)
-> Container<std::decay_t<decltype(f(*c.begin())>>
{
return {};
}
相关文章:
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 如何将lambda作为模板类的成员函数参数
- 使用自动推导的 lambda 参数作为常量表达式
- 如果模板没有可变参数,则 Lambda 被推导出为 std::function
- 将有状态的 lambda 传递到 C 样式函数中,而无需上下文参数
- 引用捕获和在 lambda 中通过引用发送参数有什么区别 (C++)
- 将__device__ lambda 作为参数传递给 __global__ 函数
- 将 lambda 函数作为参数传递C++
- 如何将 lambda 函数作为参数发送到另一个函数
- Lambda可以用作非类型模板参数吗
- 将参数传递给泛型 lambda 时复制构造函数不正确
- 如何确定捕获不可复制参数的 lambda 的类型?
- 省略C++可变参数 lambda 中的"auto"关键字?
- 如何访问可变参数 lambda 函数参数
- 可变参数 lambda 捕获的解决方法
- 传递给多个参数 lambda 表达式的参数
- 如何编写丢弃其参数的通用可变参数 lambda
- 使用c++参数lambda函数
- 将函数模板"pass"为泛型可变参数 lambda 返回语句是好方法吗?
- c++模板非类型参数lambda函数