gpt4 book ai didi

c++ - 函数类在运行时从容器中接受可变数量的参数

转载 作者:搜寻专家 更新时间:2023-10-31 01:07:56 25 4
gpt4 key购买 nike

我正在寻找一种实现函数类的方法

template<class ValueType>
class Function { ... };

它可以用一个函数指针(或仿函数)构造,它接受任意数量的 ValueType 类型的参数。并返回 ValueType .例如,给定这些函数:

double foo(double);
double bar(double, double);
int baz(double, int);

一个Function<double>对象可以用 foo 构造或 bar但不是 baz .

然后,一个成员函数call将,给定一些容器 ValueType (或迭代器),在运行时使用正确数量的参数调用底层函数。

这样的事情可能吗?

最佳答案

这确实是可能的,你只需要“递归地”从容器中解压参数并将它们传递给最深层次的函数:

#include <cstddef>
#include <utility>
#include <stdexcept>
#include <functional>
#include <type_traits>
#include <vector>
#include <iostream>

namespace detail {
template <std::size_t argument_count>
struct arguments_unpacker {
template <typename Type, typename Function, typename InputIterator, typename... UnpackedArguments>
static Type unpack(Function&& function, InputIterator arguments_begin, InputIterator arguments_end, UnpackedArguments&&... unpacked_arguments) {
if (arguments_begin == arguments_end) {
throw std::invalid_argument("Not enough arguments.");
}
return arguments_unpacker<argument_count - 1>::template unpack<Type>(std::forward<Function>(function), std::next(arguments_begin), arguments_end, std::forward<UnpackedArguments>(unpacked_arguments)..., *arguments_begin);
}
};

template <>
struct arguments_unpacker<0> {
template <typename Type, typename Function, typename InputIterator, typename... UnpackedArguments>
static Type unpack(Function&& function, InputIterator arguments_begin, InputIterator arguments_end, UnpackedArguments&&... unpacked_arguments) {
if (arguments_begin != arguments_end) {
throw std::invalid_argument("Too many arguments.");
}
return function(std::forward<UnpackedArguments>(unpacked_arguments)...);
}
};

template <typename MemberFunction>
struct member_function_arity;

template <typename Result, typename Class, typename... Arguments>
struct member_function_arity<Result(Class::*)(Arguments...)> {
static constexpr std::size_t value = sizeof...(Arguments);
};

template <typename Result, typename Class, typename... Arguments>
struct member_function_arity<Result(Class::*)(Arguments...) const> {
static constexpr std::size_t value = sizeof...(Arguments);
};

template <typename Function>
struct function_arity : member_function_arity<decltype(&Function::operator())> {};

template <typename Result, typename... Arguments>
struct function_arity<Result(*)(Arguments...)> {
static constexpr std::size_t value = sizeof...(Arguments);
};

template <typename Result, typename... Arguments>
struct function_arity<std::function<Result(Arguments...)>> {
static constexpr std::size_t value = sizeof...(Arguments);
};
}

template <typename Type, typename InputIterator, typename Function>
std::function<Type(InputIterator, InputIterator)> variate(Function function) {
using namespace detail;
return [function](InputIterator arguments_begin, InputIterator arguments_end) {
return arguments_unpacker<function_arity<Function>::value>::template unpack<Type>(function, arguments_begin, arguments_end);
};
}

namespace demo {
double a(double x0) {
std::cout << "a(" << x0 << ")\n";
return 0.0;
}

double b(double x0, double x1) {
std::cout << "b(" << x0 << ", " << x1 << ")\n";
return 0.0;
}

double c(double x0, double x1, double x2) {
std::cout << "b(" << x0 << ", " << x1 << ", " << x2 << ")\n";
return 0.0;
}

auto l = [](double x0) mutable {
std::cout << "l(" << x0 << ")\n";
return 0.0;
};

void run() {
using it = std::vector<double>::const_iterator;
auto va = variate<double, it>(&a);
auto vb = variate<double, it>(&b);
auto vc = variate<double, it>(&c);
auto vl = variate<double, it>(l);
std::vector<double> a1 = {1.0};
std::vector<double> a2 = {1.0, 2.0};
std::vector<double> a3 = {1.0, 2.0, 3.0};
va(begin(a1), end(a1));
vb(begin(a2), end(a2));
vc(begin(a3), end(a3));
vl(begin(a1), end(a1));
}
}

int main()
{
demo::run();
return 0;
}

请注意,这需要明确提供迭代器类型。我不知道如何在不编写某种类型删除 any_iterator 的情况下解决这个问题。

关于c++ - 函数类在运行时从容器中接受可变数量的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18671622/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com