【发布时间】:2017-05-08 08:57:09
【问题描述】:
我正在尝试编写一个函数,该函数基本上将在一种类型上模板化的类的实例转换为在第二种类型上模板化的同一类的实例。我想避免在调用函数时显式声明模板类型。
这是我正在尝试做的一个最小的可编译示例:
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>'
默认使用哪个版本的 g++ coliru.stacked-crooked.com:
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)> 也无济于事。
有没有办法在不显式添加模板类型的情况下将更严格指定的函数参数与 lambdas 一起使用?
【问题讨论】: