【问题标题】:Variadic templates using std::function as parameter使用 std::function 作为参数的可变参数模板
【发布时间】:2017-10-10 08:07:40
【问题描述】:

我怎样才能简化下面的代码。是否可以在这里使用元组?如果是的话,你能解释一下怎么做吗?

template<typename Out, typename T1, typename T2, typename T3, typename T4>
void ProcessIncomingCommand(PClientContext pClientContext,
    DWORD & bytesProcessed,
    const std::function<Out(T1, T2, T3, T4)> &function,
    const std::vector<UINT> &params);

template<typename Out, typename T1, typename T2, typename T3>
static void ProcessIncomingCommand(PClientContext pClientContext,
    DWORD & bytesProcessed,
    const std::function<Out(T1, T2, T3)> &function,
    const std::vector<UINT> &params);

template<typename Out, typename T1, typename T2>
static void ProcessIncomingCommand(PClientContext pClientContext,
    DWORD & bytesProcessed,
    const std::function<Out(T1, T2)> &function,
    const std::vector<UINT> &params);

需要在模板实现中调用带有std::vectorUINT 传递的参数的函数。参数可能不同,因此需要将它们转换为正确的类型。

auto resFromFunction= function(params.at(0),
    params.at(1),
    static_cast<T3>(params.at(2)),
    static_cast<T4>(params.at(3)));

我如何在这里使用log0 回答?

template<typename Out, typename... T>static void ProcessIncomingCommand(PClientContext pClientContext,
DWORD & bytesProcessed,
const std::function<Out(T...)> &function,
const std::vector<UINT> &params)

【问题讨论】:

  • 真的想在这里做什么?这段代码的目的是什么?
  • 元组会被用来做什么?
  • 在实现中,我使用由 UINT 的向量传递的参数调用函数。 vector 中的类型可能与模板参数 (T...) 不同。我需要将它们转换为适当的类型。例如:function(static_cast(params.at(0)), ... ) 等。在这里使用模板是否正确?
  • 请在问题帖子中指定参数应该做什么,您希望它如何简化,并尝试给minimal reproducible example

标签: c++ c++11 templates variadic-templates std-function


【解决方案1】:

不确定...但我想您需要一个函数助手和std::index_sequence(或类似的东西)。

一个可能的例子

template <typename Out, typename ... Ts, std::size_t ... Is>
static Out PIC_helper (
   PClientContext pClientContext,
   DWORD & bytesProcessed,
   const std::function<Out(Ts...)> &function,
   const std::vector<UINT> &params,
   std::index_sequence<Is...> const &)
 { return function( static_cast<Ts>(params.at(Is))... ); }

template <typename Out, typename ... Ts>
static void ProcessIncomingCommand (
   PClientContext pClientContext,
   DWORD & bytesProcessed,
   const std::function<Out(Ts...)> &function,
   const std::vector<UINT> &params)
 {
   Out resFromFunction
      = PIC_helper(pClientContext, bytesProcessed, function, params,
                   std::make_index_sequence<sizeof...(Ts)>());

   // other ...
 }

注意std::index_sequencestd::make_index_sequence() 是C++14 特性;但如果您需要 C++11 解决方案,您可以轻松创建一些东西来替代它们。

【讨论】:

  • 我会尝试实施您的解决方案并对其进行测试。谢谢你的回答。
  • 能否请您修复模板的返回类型。
  • @SmitYcyken - 抱歉,我不明白。
  • static void PIC_helper 返回类型“Out”而不是“void”。 ProcessIncomingCommand 没有返回值。休息没问题。请为其他有相同问题的人编辑帖子。
【解决方案2】:

这会编译。

template<typename Out, typename... T>
static void ProcessIncomingCommand(PClientContext pClientContext,
    DWORD & bytesProcessed,
    const std::function<Out(T...)> &function,
    const T&... params) { function(params...); }

int main()
{
  PClientContext p;
  DWORD d = 0.5;
  std::function<int(double, int, char)> f;
  double a;
  int b;
  char c;
  ProcessIncomingCommand(p, d, f, a, b, c);
}

如果你想将参数作为元组传递,那就更棘手了: 见How do I expand a tuple into variadic template function's arguments? 当然,如果您将 function 更改为采用元组而不是参数列表...

【讨论】:

  • 如何调用带有 N 个参数的函数?有关模板实现的信息,请查看上面的评论。
  • 好吧,我不清楚参数是否会传递给function。刚刚编辑了答案。
【解决方案3】:

看起来你想要类似的东西

template<typename ResultType, std::size_t... I>
ResultType tuple_from_vector_impl(std::vector<UINT> params, std::index_sequence<I...>)
{
    return std::make_tuple(static_cast<decltype(std::get<I>(std::declval<ResultType>()))>(params[I])...);
}

template<typename... Args, typename Indices = std::index_sequence_for<Args...>>
std::tuple<Args...> tuple_from_vector(std::vector<UINT> params)
{
    return tuple_from_vector_impl<std::tuple<Args...>>(params, Indices{});
}

template<typename Out, typename ... Args>
void ProcessIncomingCommand(PClientContext pClientContext,
                            DWORD & bytesProcessed,
                            const std::function<Out(Args...)> &function,
                            const std::vector<UINT> &params)
{
    // preamble
    std::tuple<Args...> args = tuple_from_vector<Args...>(params);
    Out result = std::apply(function, args);
    // postamble
}

template<typename ... Args>
void ProcessIncomingCommand(PClientContext pClientContext,
                            DWORD & bytesProcessed,
                            const std::function<void(Args...)> &function,
                            const std::vector<UINT> &params)
{
    // preamble
    std::tuple<Args...> args = tuple_from_vector<Args...>(params);
    std::apply(function, args);
    // postamble
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-03
    • 1970-01-01
    • 2014-05-22
    • 1970-01-01
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多