即使在阅读了许多在线资源和其他问题(包括template argument type deduction from std::function return type with lambda和Argument type auto deduction and anonymous lambda functions)之后,我仍在努力在c ++中明确表达以下内容。我想避免重复的模板参数,这似乎是不必要的。
例如,泛型“A”的容器“H”对于泛型类型“B”具有通用方法“M”。这表达了我对'H'和方法'M'的意图:
template<typename A>
struct H
{
explicit H(A x) : x(x) { }
A x;
template<typename B>
H<B> M(std::function<H<B>(A)> g) { return g(x); }
};
我的问题是调用'M'需要函数调用和返回容器的重复模板参数。对于类型'float',这不是太糟糕,但是对于其他符号,这很快就会无法管理。
// This works but requires the duplicate 'float'
H<int>(1).M<float>([](int x) { return H<float>(x + 3.14); });
// These would be preferred, but neither works
H<int>(1).M<float>([](int x) { return H(x + 3.14); });
H<int>(1).M([](int x) { return H<float>(x + 3.14); });
从this question开始,我尝试使用通用仿函数类型'F'而不是通用结果类型来定义'H'的新定义:
template<typename A>
struct H2
{
enum { IS_H2 = true };
explicit H2(A x) : x(x) { }
A x;
template<typename F,
class = typename std::enable_if<std::result_of<F(A)>::type::IS_H2>::type>
auto M(F g) -> decltype(g(x)) { return g(x); }
};
允许使用所需的语法:
// This now is valid
H2<int>(1).M([](int x) { return H2<float>(x + 3.14); });
// And, as expected, this is not
H2<int>(1).M([](int x) { return x + 3.14; });
但我发现'H2'几乎令人反感,必须有更好的方法。
如何更加干净地限制仿函数的泛型返回类型,或者使用std :: function来处理类型推断?还是我完全从错误的角度攻击问题?
答案 0 :(得分:1)
这就是函数模板的工作原理,并且没有办法解决。
如果在函数参数中有参数,则完成自动模板参数推导,这不是这种情况。例如,编译器可以在此函数中推断出类型:
template<typename B>
H<B> M(std::function<H<B>(A)> g, const B&) { return g(x); }
然后你必须传递一些虚拟值,这是(我认为)不是你想要的。
这是一个示例,它无法将lambda转换为std :: function,因为模板参数推断失败:
#include <functional>
template<typename A>
struct H
{
explicit H(A x) : x(x) { }
A x;
template<typename B>
H<B> M(std::function<H<B>(A)> g, const B&) { return g(x); }
};
int main()
{
H<int> h(1);
std::function<H<float>(int)> g( [](int x){ return H<float>(x + 3.14); } );
const auto v = h.M( g, 5.5f );
(void)v;
}