c++ 11使用std::函数进行类型演绎

C++11 Type Deduction With std::function

本文关键字:类型 演绎 函数 使用 std c++      更新时间:2023-10-16

即使在阅读了许多在线资源和其他问题之后,包括从std::函数返回类型使用lambda和参数类型自动扣除和匿名lambda函数的模板参数类型扣除,我仍然难以在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); });

从这个问题开始,我尝试用泛型函子类型'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::函数与类型推断一起工作?还是我完全从错误的角度切入了问题?

函数模板就是这样工作的,没有别的办法。

如果函数形参中有一个形参,则自动进行模板形参推导,这里不是这种情况。例如,编译器可以在以下函数中推断类型:

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;
}