使用 std::function 的 C++11 类型推导

标签 c++ c++11 std type-deduction

即使阅读了许多在线资源和其他问题,包括 template argument type deduction from std::function return type with lambdaArgument 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 与类型推断一起工作?还是我完全从错误的角度来解决问题?

最佳答案

这就是函数模板的工作方式,没有其他办法。

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

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

关于使用 std::function 的 C++11 类型推导,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17183761/

相关文章:

c++ - 堆栈检查 C++ 中的 html 标签平衡

android - 是否可以在 gcc 编译器中使用 clang std 库?

c++ - 在 Windows 上编译 C++ (Mingw/Cygwin)

c++ - cpp string find() 没有按预期工作 - 返回大的垃圾值

c++ - 使用带有类错误的 map ,编译错误

c++ - 如何在 C++ 中使用类原型(prototype)

c++ - vector 范围构造函数如何在下面的类中工作?

c - 我的错误是什么?

c++ - 只在运行时知道数据类型。如何向使用它们的其他类隐藏数据详细信息

c++ - 多映射中的 std::find_if 返回带有仿函数的错误