【问题标题】:Extracting function argument types as a parameter pack提取函数参数类型作为参数包
【发布时间】:2015-09-04 18:21:44
【问题描述】:

这是"unpacking" a tuple to call a matching function pointer 的后续问题,该问题询问如何以通用方式将std::tuple 中的值作为参数提供给函数。给出的解决方案如下:

template<int ...>
struct seq { };

template<int N, int ...S>
struct gens : gens<N-1, N-1, S...> { };

template<int ...S>
struct gens<0, S...>
{
   typedef seq<S...> type;
};

double foo(int x, float y, double z)
{
   return x + y + z;
}

template <typename... Args>
struct save_it_for_later
{
   std::tuple<Args...> params;
   double (*func)(Args...);

   double delayed_dispatch()
   {
    return callFunc(typename gens<sizeof...(Args)>::type());
   }

   template<int ...S>
   double callFunc(seq<S...>)
   {
    return func(std::get<S>(params) ...);
   }
};

int main(void)
{
   std::tuple<int, float, double> t = std::make_tuple(1, 1.2, 5);
   save_it_for_later<int,float, double> saved = {t, foo};
   std::cout << saved.delayed_dispatch() << std::endl;
}

我的问题是是否有办法制作 save_it_for_later 的替代版本,它只将 foo 作为模板参数,这样我们就不必提供 foo 的参数类型作为模板参数(或将其返回类型烘焙到save_it_for_later)。类似的东西

int main(void) {
   ...
   save_it_for_later2<foo> saved = {t};
   ...
}

我同样可以使用某种宏包装 foo 来提取所需的类型:

int main(void) {
   ...
   save_it_for_later<MACRO_USING_DECLTYPE_OR_SOMESUCH(foo)> saved = {t};
   ...
}

这种担忧似乎与最初的问题完全正交,足以证明自己的立场。

【问题讨论】:

  • 什么是foo?如果它是一个具有多个operator() 重载的通用函子,您应该使用哪个重载?例如,如果foo 只是一个函数指针或std::function,这很容易做到。一般情况很难。
  • foo 只是一个函数指针,如上例所示。

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


【解决方案1】:
#include <tuple>
#include <utility>

template <typename> struct save_it_for_later_t;
template <typename Result, typename... Args>
struct save_it_for_later_t<Result (*)(Args...)> {
    std::tuple<Args...>   params;
    Result              (*fun)(Args...);
    template <typename... Params>
    save_it_for_later_t(Result (*fun)(Args...), Params&&... params)
        : params(std::forward<Params>(params)...)
        , fun(fun) {
    }
    // ... 
};
template <typename Result, typename... Args, typename... Params>
save_it_for_later_t<Result(*)(Args...)>
save_it_for_later(Result (*fun)(Args...), Params&&... params) {
    return save_it_for_later_t<Result(*)(Args...)>(fun, std::forward<Params>(params)...);
}

double foo(float, float, double);
int main() {
    auto saved = save_it_for_later(foo, 1.2f, 3.4f, 5.6);
    // ...
}

【讨论】:

  • 太棒了!对于奖励积分,是否可以将foo 本身设为模板参数(而不是类成员)?长话短说,但在我的情况下——这与上面的人工示例不同——这实际上非常有用。
  • 实际上,在获得奖励积分之前,您的解决方案似乎不太正确;你能提供一个你检查过编译的完整解决方案吗?
  • @factotum:是的,有一些小错别字。这些是固定的。
【解决方案2】:

我只是不好意思地发现去年我问了一个类似的问题 (Unpacking arguments of a functional parameter to a C++ template class),这也产生了答案:

#include <functional>
#include <iostream>
#include <tuple>

template<int ...>
struct seq { };

template<int N, int ...S>
struct gens : gens<N-1, N-1, S...> { };

template<int ...S>
struct gens<0, S...>
{
   typedef seq<S...> type;
};

double foo(int x, float y, double z)
{
   return x + y + z;
}

template<typename T>
struct save_it_for_later;

template <typename Result, typename... Args>
struct save_it_for_later<Result(Args...)>
{
   std::tuple<Args...> params;
   Result (*func)(Args...);

   Result delayed_dispatch()
   {
    return callFunc(typename gens<sizeof...(Args)>::type());
   }

   template<int ...S>
   Result callFunc(seq<S...>)
   {
    return func(std::get<S>(params) ...);
   }
};

int main(void)
{
   std::tuple<int, float, double> t = std::make_tuple(1, 1.2, 5);
   save_it_for_later<decltype(foo)> saved = {t, foo};
   std::cout << saved.delayed_dispatch() << std::endl;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    • 2018-08-27
    • 2021-07-22
    • 2018-11-30
    • 2021-07-31
    相关资源
    最近更新 更多