Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 编译时确定参数数的Lambda函数_C++_Templates_C++11_Lambda_C++14 - Fatal编程技术网

C++ 编译时确定参数数的Lambda函数

C++ 编译时确定参数数的Lambda函数,c++,templates,c++11,lambda,c++14,C++,Templates,C++11,Lambda,C++14,我想声明一个具有N个参数的lambda函数,其中N是一个模板参数。类似于 template <int N> class A { std::function<void (double, ..., double)> func; // exactly n inputs }; 模板 甲级{ std::函数func; //正是n个输入 }; 我想不出用元函数范式实现这一点的方法。你可以用嵌套的typedeftype编写一个

我想声明一个具有N个参数的lambda函数,其中N是一个模板参数。类似于

template <int N>
class A {
    std::function<void (double, ..., double)> func;
                        // exactly n inputs
};
模板
甲级{
std::函数func;
//正是n个输入
};

我想不出用元函数范式实现这一点的方法。

你可以用嵌套的typedef
type
编写一个模板
n_-ary\u函数
。此类型可按如下方式使用:

template <int N>
class A {
    typename n_ary_function<N, double>::type func;
};

你不能直接这么做

你可以这样做

template <unsigned N> class UniformTuple;

template <>
class UniformTuple <0>
{
};

template <unsigned N>
class UniformTuple : public UniformTuple <N-1>
{
public:

    template <typename... Args>
    UniformTuple (double arg, Args... args)
    : UniformTuple <N-1> (args...)
    , m_value (arg)
    {
    }

private:

    double m_value;
};

template <int N>
class A
{
    std :: function <void (const UniformTuple <N> &)> func;
};
模板类UniformTuple;
模板
类UniformTuple
{
};
模板
类UniformTuple:公共UniformTuple
{
公众:
模板
UniformTuple(双参数,参数…参数)
:UniformTuple(参数…)
,m_值(arg)
{
}
私人:
双m_值;
};
模板
甲级
{
std::函数func;
};

一个元
模板
,它接受一个模板、一个计数和一个类型,并使用该类型的
N
副本调用该模板:

template<template<class...>class target, unsigned N, class T, class... Ts>
struct repeat_type_N: repeat_type_N<target, N-1, T, T, Ts...> {};
template<template<class...>class target, class T, class... Ts>
struct repeat_type_N<target, 0, T, Ts...> {
  typedef target<Ts...> type;
};
template<template<class...>class target, unsigned N, class T>
using repeat_type_N_times = typename repeat_type_N<target, N, T>::type;

对于较大的
N
,上述方法可以显著减少编译时间,并处理
模板
堆栈溢出的问题。

为了完整起见,这里有一个无递归的解决方案:

template <class Ret, class Arg, class Idx>
struct n_ary_function_;

template <class Ret, class Arg, std::size_t... Idx>
struct n_ary_function_<Ret, Arg, std::index_sequence<Idx...>> {
    template <class T, std::size_t>
    using id = T;

    using type = std::function<Ret(id<Arg, Idx>...)>;
};

template <class Ret, class Arg, std::size_t N>
using n_ary_function = typename n_ary_function_<
    Ret, Arg, std::make_index_sequence<N>
>::type;
模板
结构元函数;
模板
结构元函数{
模板
使用id=T;

使用type=std::function lambda表达式在哪里?该类将存储一个lambda表达式。假设在构造函数中对其进行了初始化以确定(在我的特定应用程序中不一定如此).1.我考虑过这种方法。它不理想,但可能是唯一的方法。另一个想法是使用
虚拟get(const double*参数)
定义我自己的函数类,并使用可变模板实现
操作符()
(并在
操作符()
中执行
静态断言
)。这也不太理想,但有点接近我所需要的能力。@nosid偷了你的解决方案,让它成为通用的东西。
template<typename... Ts> using operation=void(Ts...);
template<unsigned N, class T> using N_ary_op = repeat_type_N_times< operation, N, T >;
template<unsigned N> using N_double_func = N_ary_op<N,double>;
void three_doubles(double, double, double) {}

int main() {
  N_double_func<3>* ptr = three_doubles;
  std::function< N_double_func<3> > f = three_doubles;
}
// package for types.  The typedef saves characters later, and is a common pattern in my packages:
template<class...>struct types{typedef types type;};

// Takes a target and a `types`, and applies it.  Note that the base has no implementation
// which leads to errors if you pass a non-`types<>` as the second argument:
template<template<class...>class target, class types> struct apply_types;
template<template<class...>class target, class... Ts>
struct apply_types<target, types<Ts...>>{
  typedef target<Ts...> type;
};
// alias boilerplate:
template<template<class...>class target, class types>
using apply_types_t=typename apply_types<target,types>::type;

// divide and conquer, recursively:
template<unsigned N, class T, class Types=types<>> struct make_types:make_types<
  (N+1)/2, T, typename make_types<N/2, T, Types>::type
> {};

// terminate recursion at 0 and 1:
template<class T, class... Types> struct make_types<1, T, types<Types...>>:types<T,Types...> {};
template<class T, class Types> struct make_types<0, T, Types>:Types{};

// alias boilerplate:
template<unsigned N, class T>
using make_types_t=typename make_types<N,T>::type;

// all of the above reduces `repeat_type_N_t` to a one-liner:    
template<template<class...>class target, unsigned N, class T>
using repeat_type_N_times = apply_types_t<target, make_types_t<N,T>>;
template <class Ret, class Arg, class Idx>
struct n_ary_function_;

template <class Ret, class Arg, std::size_t... Idx>
struct n_ary_function_<Ret, Arg, std::index_sequence<Idx...>> {
    template <class T, std::size_t>
    using id = T;

    using type = std::function<Ret(id<Arg, Idx>...)>;
};

template <class Ret, class Arg, std::size_t N>
using n_ary_function = typename n_ary_function_<
    Ret, Arg, std::make_index_sequence<N>
>::type;