繁体   English   中英

推导std :: function结果类型并将其用作参数

[英]Deduce the std::function result type and use it as a parameter

这就是我的简单课程的样子。

template <class T>
class A {
T first;
T second;

public:
A(T f, T s) : first(f), second(s) {};

template <class F>
auto foo(F f) -> decltype(f(T(), T())) {
    return f(first, second);
}
};

int main() {
    A<int> a = A<int>(2, 3);
    a.foo([](int l, int r)->int{return l + r;});
}

我想让foo接受一个函数(或lambda或fucntion指针)f,它接受两个T类型的属性并返回f()的结果。

这段代码有效,但是我创建了虚拟参数来获取decltype的结果。 在这种情况下,它们是简单的整数,但是可以是任何整数,我当然不想从更大的类构造伪参数。 怎么处理呢?

而且,这只是一种简化的情况。 在我的情况下,foo看起来像这样:

foo(function f, result_type_of_f t1, result_type_of_f t2) {
    // do something
    return f(first, second, t1, t2);
}

我无法使用与第一个类似的方法来执行此操作,我还尝试了本文中的方法确定std :: function的返回类型,但无济于事。

随意创建所需的参数作为decltype复合体。

decltype在编译时进行评估,并且不会生成任何代码。 编译器将以“空运行”模式经历构造所有参数的动作,找出产生的返回类型并使用它。

的确,对于复杂的C ++代码,由于decltype ,模板和其他构造函数的原因,编译器必须做的所有工作确实会使编译速度变慢。 但是无论decltype d是什么, decltype最终都不会导致运行时开销。

假设没有麻烦的重载类函数,我们可以实现resultOf类型特征来获取返回类型:

// std::void_t from C++17
template <class...>
struct voider {
    using type = void;
};

template <class... T>
using void_t = typename voider<T...>::type;

namespace detail_resultOf {

    // Base case, when it cannot be deduced
    template <class F, class = void_t<>>
    struct resultOf { };

    // Function object: grab its operator() and try again
    template <class F>
    struct resultOf<F, void_t<decltype(&F::operator())>>
    : resultOf<decltype(&F::operator())> { };

    // Member functions
    template <class Ret, class T, class... Args>
    struct resultOf<Ret (T::*)(Args...)> {
        using type = Ret;
    };

    // ...

    // Free functions

    template <class Ret, class... Args>
    struct resultOf<Ret (*)(Args...)> {
        using type = Ret;
    };

    // ...
}

// Public metafunction
template <class F>
using resultOf = typename detail_resultOf::resultOf<F>::type;

在Coliru上实时观看

然后,您可以将函数编写为:

template <class F>
auto foo(F f, resultOf<F> t1, resultOf<F> t2) -> resultOf<F> {
    // do something
    return f(first, second, t1, t2);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM