Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.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++ 使用模板元编程将模板函数布尔参数转换为运行时函数参数_C++_Templates_C++11_Metaprogramming_Template Meta Programming - Fatal编程技术网

C++ 使用模板元编程将模板函数布尔参数转换为运行时函数参数

C++ 使用模板元编程将模板函数布尔参数转换为运行时函数参数,c++,templates,c++11,metaprogramming,template-meta-programming,C++,Templates,C++11,Metaprogramming,Template Meta Programming,我有一个函数,它接受几个布尔模板参数: template<bool par1, bool par2, bool par2> void function(int arg1, int arg2, int arg3); template<template<bool> class T> class CombinationsOfTemplateParameters; template<template<bool, bool> class T>

我有一个函数,它接受几个布尔模板参数:

template<bool par1, bool par2, bool par2>
void function(int arg1, int arg2, int arg3);
template<template<bool> class T> class CombinationsOfTemplateParameters;
template<template<bool, bool> class T> class CombinationsOfTemplateParameters;
template<template<bool, bool, bool> class T> class CombinationsOfTemplateParameters;
//and so on, up to some implementation defined hard limit.
我认为,如果希望对类执行相同的操作,而不是使用模板函数,则可以执行此操作,这要感谢模板参数:

template<bool par1, bool par2, bool par2>
void function(int arg1, int arg2, int arg3);
template<template<bool> class T> class CombinationsOfTemplateParameters;
template<template<bool, bool> class T> class CombinationsOfTemplateParameters;
template<template<bool, bool, bool> class T> class CombinationsOfTemplateParameters;
//and so on, up to some implementation defined hard limit.
模板类组合SoftemplateParameters;
模板类组合SoftemplateParameters;
模板类组合SoftemplateParameters;
//等等,直到一些实现定义的硬限制。
但据我所知,没有办法指向通用模板函数,而不指定其模板参数。因此,首先,我不知道如何将它传递给模板参数列表中的某个助手类


有办法解决这个问题吗?

第一步,为了理解这个问题,我将为每个实例化构造一个函数指针数组:

void runtime_function(bool par1, bool par2, bool par3, int arg1, int arg2, int arg3);
template<bool, bool, bool> void function(int, int, int);

typedef void (*func_type)(int, int, int);

func_type funcs[] = {
    &function<false, false, false>,
    &function<false, false, true>,
    &function<false, true,  false>,
    &function<false, true,  true >,
    &function<true,  false, false>,
    &function<true,  false, true >,
    &function<true,  true,  false>,
    &function<true,  true,  true >
};
template<bool, bool, bool> void function(int, int, int);

typedef void (*func_type)(int, int, int);

template<typename> struct make_table;

template<int... N>
  struct make_table<seq<N...>>
  {
    static const func_type funcs[sizeof...(N)];
  };

template<int... N>
  const func_type make_table<seq<N...>>::funcs[sizeof...(N)] = {
    &function< bool(N&4), bool(N&2), bool(N&1) >...
  };
因此,您可以使用按位运算形成的整数对数组进行索引:

void runtime_function(bool par1, bool par2, bool par3, int arg1, int arg2, int arg3)
{
  func_type f = funcs[ int(par1)<<2 | int(par2)<<1 | int(par3) ];
  f(arg1, arg2, arg3);
};
然后在包扩展中使用它来生成每个可能的实例化:

void runtime_function(bool par1, bool par2, bool par3, int arg1, int arg2, int arg3);
template<bool, bool, bool> void function(int, int, int);

typedef void (*func_type)(int, int, int);

func_type funcs[] = {
    &function<false, false, false>,
    &function<false, false, true>,
    &function<false, true,  false>,
    &function<false, true,  true >,
    &function<true,  false, false>,
    &function<true,  false, true >,
    &function<true,  true,  false>,
    &function<true,  true,  true >
};
template<bool, bool, bool> void function(int, int, int);

typedef void (*func_type)(int, int, int);

template<typename> struct make_table;

template<int... N>
  struct make_table<seq<N...>>
  {
    static const func_type funcs[sizeof...(N)];
  };

template<int... N>
  const func_type make_table<seq<N...>>::funcs[sizeof...(N)] = {
    &function< bool(N&4), bool(N&2), bool(N&1) >...
  };
它打印:

f<false, true, true>(1, 2, 3)
f<true, false, false>(4, 5, 6)
并添加
genrevs
以创建整数的反向序列,
seq
,该序列被传递到该函数以用作
掩码
参数包:

gen_func<I>(typename genrevs<NParams>::type()) ...
这是完整的最终版本。昨晚写了这段代码之后,我意识到它假设函数参数
(int,int,int)
的数量与模板参数
的数量相同,如果不是这样,那么您需要向
make_table
添加一个额外的非类型模板参数,指定模板参数的数量(在下面的代码中,这是
NParams
并已推导):

#包括
模板
结构序列{};
模板
结构gens:gens{};
模板
结构族{
typedef-seq-type;
};
模板
结构genrevs:genrevs{};
模板
结构genrevs{
typedef-seq-type;
};
模板无效函数(int,int,int);
模板
结构pow2
{
static constexpr unsigned value=2*pow2::value;
};
模板结构pow2{static constexpr unsigned value=1;};
模板结构制表顺序;
模板
结构制作表
:氏族
{ };
模板
构造make_表;
模板
班级制作表
{
static const unsigned NParams=sizeof…(参数);
公众:
typedef Res(*func_type)(参数…);
模板
静态类型名称std::enable_if::type
得到(Bool…b)
{return funcs[shift_或(0,b..)];}
私人:
模板
静态constexpr func类型gen func(seq)

{return&function我特别想要避免的是您的第一步,即手动创建实例化表。这只是一项正在进行的工作,以证明它是一个二进制数表。示例的其余部分不使用它。请仔细查看:)抱歉,太晚了:)我明天会仔细检查。
template<unsigned N, int... Mask>
  static constexpr func_type gen_func(seq<Mask...>)
  { return &function<(N&(1<<Mask))...>; }
gen_func<I>(typename genrevs<NParams>::type()) ...
void runtime_function(bool par1, bool par2, bool par3, int arg1, int arg2, int arg3)
{
  auto f = make_table<void(int, int, int)>::get(par1, par2, par3);

  f(arg1, arg2, arg3);
}
#include <type_traits>

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;
};

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

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

template<bool, bool, bool> void function(int, int, int);

template<unsigned N>
  struct pow2
  {
    static constexpr unsigned value = 2*pow2<N-1>::value;
  };

template<> struct pow2<0> { static constexpr unsigned value = 1; };

template<typename Signature> struct make_table_seq;

template<typename Res, typename... Params>
  struct make_table_seq<Res(Params...)>
  : gens<pow2<sizeof...(Params)>::value>
  { };

template<typename Signature, typename = typename make_table_seq<Signature>::type>
struct make_table;

template<typename Res, typename... Params, int... I>
  class make_table<Res(Params...), seq<I...>>
  {
    static const unsigned NParams = sizeof...(Params);

  public:
    typedef Res (*func_type)(Params...);

    template<typename... Bool>
      static typename std::enable_if<sizeof...(Bool)==NParams, func_type>::type
      get(Bool... b)
      { return funcs[ shift_or(0, b...) ]; }

  private:
    template<unsigned N, int... Mask>
      static constexpr func_type gen_func(seq<Mask...>)
      { return &function<(bool(N&(1<<Mask)))...>; }

    template<typename... Bool>
      static int shift_or(int i, bool b0, Bool... b)
      {
        return shift_or((i<<1) | int(b0), b...);
      }

    static int shift_or(int i) { return i; }

    static const func_type funcs[sizeof...(I)];
  };

template<typename Res, typename... Params, int... I>
  const typename make_table<Res(Params...), seq<I...>>::func_type
  make_table<Res(Params...), seq<I...>>::funcs[] = {
    gen_func<I>(typename genrevs<NParams>::type()) ...
  };

// specialise for function pointer types as well as function types
template<typename Res, typename... Params>
  struct make_table_seq<Res(*)(Params...)>
  : make_table_seq<Res(Params...)>
  { };

template<typename Res, typename... Params, typename T>
  class make_table<Res(*)(Params...), T>
  : make_table<Res(Params...)>
  { };