从作为模板函数参数传递的std :: function推断返回值和参数类型?

时间:2019-04-04 15:48:59

标签: c++ templates std-function

我一直在四处寻找SO,但是找不到我一直在寻找的答案-this question可能最接近我的想法。

用一句话:是否可以声明一个带有protected function execute(InputInterface $input, OutputInterface $output) { $now = new DateTimeImmutable(); $io = new SymfonyStyle($input, $output); $query = $this->objectManager ->getRepository(Order::class) ->createQueryBuilder('o') ->where('o.isReservation = :reservationStatus') ->andWhere('o.expireTime BETWEEN :now AND :max') ->setParameter('reservationStatus', 1) ->setParameter('now', $now) ->setParameter('max', $now->add(new DateInterval('PT24H'))); } 参数并为该函数的返回类型和参数类型推导出模板参数的模板函数?示例:

std::function

这是因为函数签名或函数类型本身被视为一件事情,因此不能被“分解”吗?我意识到有//this works to pass the std::function in template<class T> void doSomething(std::function<T> f) { f(); } //this is more what i am looking for - can R and P be deduced automatically - does not work! template<class R, class P> void doSomethingElse(std::function<R(P)> f) { f(); } decltype,但无法思考我在这里如何使用它们。

还有一点,我如何使用可变参数模板将第二个示例扩展为具有多个参数和推导?

1 个答案:

答案 0 :(得分:3)

template<class R, class P>
void doSomethingElse(std::function<R(P)> f) {
    f(P{});
}

将起作用,但是仅当您将std::function传递给该函数并且该函数具有一个非void参数时,该函数才起作用。不过,这是一种限制。您可以使用

template<class R, class... Args, class... Ts>
void doSomethingElse(std::function<R(Args...)> f, Ts&&... args) {
    f(std::forward<Args>(args)...);
}

这将采用任何std::function及其参数,并像在呼叫站点中一样进行调用。但是,这仍然是有限制的,因为呼叫站点要求您使用std::function,因此您不能将任何隐式可转换为std::function的内容传递给它。

对于C ++ 17和class template argument deduction(CTAD),这不再是问题。我们可以创建任何类型的重载,然后使用CTAD构造一个std :: function来为我们填充类型。看起来像

template<class Func, class... Args>
void doSomethingElse(Func&& f, Args&&... args) {
    doSomethingElse(std::function{std::forward<Func>(f)}, std::forward<Args>(args)...);
}

template<class R, class... Args, class... Ts>
void doSomethingElse(std::function<R(Args...)> f, Ts&&... args) {
    f(std::forward<Args>(args)...);
}

现在,不是std::function的所有内容都将转到void doSomethingElse(Func&& f, Args&&... args),转换为std::function,然后传递给void doSomethingElse(std::function<R(Args...)> f, Args&&... args),以便您可以使用返回值类型和参数在那里。