【问题标题】:c++ template parameter compiler can not deducec++模板参数编译器无法推断
【发布时间】:2020-01-21 16:53:24
【问题描述】:

这里是注册函数。

template <typename ReqT, typename RespT>
bool RegisterCmdHandler(int cmd_id, std::function<int(int, const ReqT&, RespT&)> sync_handler) {
    // ... do something with sync_handler and register it for later callback
    return true;
}

以及要注册的特定处理程序:

int SomeHandler(int id, const Foo& req, Bar& resp) {
    // ... specific logic
}

现在我想将处理程序应用到注册函数,编译器抱怨

RegisterCmdHandler(1, SomeHandler); // ERROR, compiler can not deduce

虽然具体写出类型就OK了:

RegisterCmdHandler<Foo, Bar>(1, SomeHandler); // OK, compiler can deduce

但后者有丑陋的 API。我怎样才能在工作中获得第一名?

【问题讨论】:

  • TL;DR:模板从不进行转换。 SomeHandler不是std::function,所以无法推断出std::function的类型。
  • @NathanOliver 建议的重复问题不回答“我如何在工作中获得第一个?”。
  • 如果你只打算使用普通函数,你可以使用函数指针来代替。

标签: c++ boost template-meta-programming std-function template-argument-deduction


【解决方案1】:

我怎样才能在工作中获得第一名?

为普通函数指针添加重载:

template <typename ReqT, typename RespT>
bool RegisterCmdHandler(int cmd_id, int(*sync_handler)(int, const ReqT&, RespT&)) {
    std::function<int(int, const ReqT&, RespT&)> sync_handler2(sync_handler);
    return RegisterCmdHandler(cmd_id, sync_handler2);
}

【讨论】:

    【解决方案2】:

    我怎样才能在工作中获得第一名?

    我看到了一些方法。

    (1)如果你可以修改RegisterCmdHandler()函数并且你不需要知道,里面ReqTRestT是什么类型,建议你避免完全没有 std::function 并接受 sync_handler 作为简单的模板类型。

    我是说

    template <typename F>
    bool RegisterCmdHandler (int cmd_id, F sync_handler) {
    // ... do something with sync_handler
    return true;
    }
    

    这是一个非常灵活的解决方案,因为F可以是一个函数,一个函数指针,一个std::function,一个lambda(也是一个通用的lambda,所以这个解决方案比使用std::function更灵活),另一种类型具有operator() 的类/结构,从std::bind 返回的值。简而言之:一个通用的可调用对象。

    (2)如果你可以修改RegisterCmdHandler()函数但是你需要知道(和使用)ReqTRestT,你可以按照普通函数指针的方式(见Maxim Egorushkin 对语法的回答)。不幸的是,这仅适用于函数指针,并且在 sync_handler 是 lambda 时不起作用(例如)。

    (3)如果不能修改RegisterCmdHandler()但可以使用C++17,可以使用std::function推导,调用函数如下

    RegisterCmdHandler(1, std::function{SomeHandler}); 
    

    或者,如果您必须在不同的地方调用它,可能会更好,通过转换器调用它

    template <typename F>
    auto CallRegisterCH (int cmd_if, F && func)
     { return RegisterCmdHandler(cmd_if, std::function{std::forward<F>(func)}); }
    

    这样称呼它

    CallRegisterCH(1, SomeHandler);
    

    (4) 如果你不能修改RegisterCmdHandler() 并且你必须使用 C++11 或 C++14...好吧...解释模板类型

    RegisterCmdHandler<Foo, Bar>(1, SomeHandler); 
    

    在我看来是更好的方法。

    您可以通过其他方式显式 std::function

    std::function<int(int, Foo const &, Bar &)>  sh{ SomeHandler };
    
    RegisterCmdHandler(1, sh);
    

    但在我看来几乎是一样的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-09
      • 2010-10-17
      • 1970-01-01
      • 1970-01-01
      • 2017-06-16
      • 2014-11-20
      • 1970-01-01
      相关资源
      最近更新 更多