c++ - 如何生成与函数的数量一样多的参数?

标签 c++ c++11

假设我有以下函数,它接受一个函数作为参数。

template <typename F>
void test_func(F f)
{
    // typedef typename function_traits<F>::return_type T;
    typedef int T;

    std::mt19937 rng(std::time(0));
    std::uniform_int_distribution<T> uint_dist10(0, std::numeric_limits<T>::max());

    f(uint_dist10(rng), uint_dist10(rng)); // Problem!
}

用法如下:

int foo(int, int) { return 0; }
int bar(int, int, int, int) { return 0; }

int main()
{
    test_func(foo);
    // test_func(bar);
}

就像 foobar 一样,我有几个返回 T 的函数,并接受一些 T 类型的参数。我希望 test_func 生成对我的 RNG 的调用,因为函数 f 需要参数。换句话说,我们可以假设 T 始终是整数类型,并且每个参数都是相同的,即对 RNG 的函数调用。

使用 function_traits(例如 the ones in Boost ),我可以获取 F 的返回类型,这有点帮助。大致来说,我的问题是

How can I generate a needed amount of function calls so that it matches the arity of the function F?

在 C++11 之前,我会研究 Boost.Preprocessor,或者可能依赖于模板特化。现在有更好的方法吗?

最佳答案

首先定义一个名为 arity 的元函数来计算函数的元数(这只是一个简单的实现;也可以改进为计算仿函数的元数。请参阅我的答案 here。):

template<typename F> 
struct arity;

template<typename R, typename ...Args> 
struct arity<R (*)(Args...)>
{
    static const std::size_t value = sizeof ... (Args);
};

然后定义另一个名为 genseq 的元函数来生成整数值的编译时间序列:

template<int ... N>
struct seq
{
    using type = seq<N...>;

    template<int I>
    struct push_back : seq<N..., I> {};
};

template<int N>
struct genseq : genseq<N-1>::type::template push_back<N-1> {};

template<>
struct genseq<0> : seq<> {};

template<int N>
using genseq_t = typename genseq<N>::type;  //Just a friendly alias!

然后是函数调用者:

template<typename F, typename ArgEvaluator, int ...N>
void invoke(seq<N...>, F f, ArgEvaluator arg_evaluator)
{
    using arg_type = decltype(arg_evaluator());

    constexpr std::size_t arity = sizeof ... (N);

    arg_type args[] { (N, arg_evaluator()) ... }; //enforce order of evaluation

    f( args[N] ... );
}

然后你的代码会变成这样:

template <typename F>
void test_func(F f)
{
    // typedef typename function_traits<F>::return_type T;
    typedef int T;

    std::mt19937 rng(std::time(0));
    std::uniform_int_distribution<T> uint_dist10(0, std::numeric_limits<T>::max());

    //f(uint_dist10(rng), uint_dist10(rng)); // Problem!

      auto arg_evaluator = [&]() mutable { return uint_dist10(rng); };
      invoke(genseq_t<arity<F>::value>(), f, arg_evaluator);
}

Here is a sample demo .

希望对您有所帮助。

关于c++ - 如何生成与函数的数量一样多的参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23649458/

相关文章:

c++ - 我可以在 std::function 中使用模板类型 T 来传递 lambda 类型函数 C++11 吗?

c++ - 在类实例化期间未设置继承值

c++ - 具有运行时分配的指针

c# - VS2015 — 将 CRL 与 C++ DLL 链接起来

c++ - 在 C++11 中可移植地打印 std::uint64_t 变量的格式说明符

c++11 emplace_back 和 push_back 语法与结构

c++ - 引用你不拥有的 "std::unique_ptr"(使用原始指针?)

c++ - Boost正则表达式如何将Cookie字符串解析为map<string, string>?

Android - NDK - C++ - 无法使用 'int *' 类型的右值(又名 'jlong *')初始化 'long long *' 类型的变量

c++ - For循环性能和多线程性能问题