c++ - 无法推导 std::function 模板参数

标签 c++ templates c++17 std-function template-argument-deduction

我正在编写如下代码

#include <functional>

template <typename Type>
void foo(const std::function<void(const Type&)> & handler) {}

void goo (const int&){}

int main() {
    foo([](const int&){});
    foo(goo);
}

不幸的是,由于以下错误,它拒绝在(clang 6.0.0 和 gcc 8.1.1)上编译

candidate template ignored: could not match 'function<void (const type-parameter-0-0 &)>' against '(lambda at test3.cpp:13:9)'
candidate template ignored: could not match 'function<void (const type-parameter-0-0 &)>' against '(lambda at test3.cpp:13:9)'

是否有可能以某种方式强制它正确推断类型

最佳答案

您标记了 C++17,因此您可以使用 std::function 的推导指南。

你可以试试下面的方法

template <typename F,
          typename Type = typename decltype(std::function{std::declval<F>()})::argument_type>
void foo (F f)
 {
 }

我知道 argument_type 在 C++17 中已被弃用,但您可以用一个简单的自定义模板代替它。

举例

template <typename>
struct firstArg;

template <typename R, typename A0, typename ... As>
struct firstArg<std::function<R(A0, As...)>>
 { using type = A0; };

foo()可以写成

template <typename F,
          typename FUNC = decltype(std::function{std::declval<F>()}),
          typename Type = typename firstArg<FUNC>::type>
void foo (F f)
 {
 }

这样可调用的 f 不是 std::function 而是原始类型(这可能更好也可能更坏,具体取决于您的具体要求);如果您在 std::function 中需要它,您可以使用再次推导指南或 FUNC 类型在 foo() 函数中获取它

template <typename F,
          typename FUNC = decltype(std::function{std::declval<F>()}),
          typename Type = typename firstArg<FUNC>::type>
void foo (F f)
 {
   FUNC fnc{f};
 }

关于c++ - 无法推导 std::function 模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51234100/

相关文章:

c++ - 可组合的 monadic lambda/std::function with std::optional

c++ - 将整数常量映射到类型

c++ - 为指向集合的指针重载开始/结束是个好主意吗

从数组维度推导 C++ 模板参数

c++ - 自记录类型别名(typedef)以指示它将在另一个特定类中使用

c++ - 为什么成员函数不能用作模板参数?

templates - 如何在 Grails 中部分更新布局/模板

c++ - 在哪些情况下 std::optional operator == 会导致未定义的行为?

c++ - 如何在同一个项目中运行多个不同的项目?

c++ - 如何在 C++ 中创建多维?