3

私自身、可変個引数テンプレートを使用したことはありませんが、今は必要になると思います。クラスがあるとします

class A {
  int Kern;
  template<int> void func_a(int, double) const;
  template<int> void func_b(double, double, char) const;
  template<int> unsigned func_c(float, std::vector<int> const&) const;
public
  /* ... */
  void FuncA(int, double) const;
  void FuncB(double, double, char) const;
  unsigned FuncC(float, std::vector<int> const&) const;
};

etc.の定義A::FuncA()はすべて次の形式です。

void A::FuncA(int i, double x) const
{
   switch(Kern) {
   case 1: return func_a<1>(i,x);
   case 2: return func_a<2>(i,x);
   case 3: return func_a<3>(i,x);
   /* ... */
   }
 }

現在、このスイッチを C マクロで実装しています

#define SwitchKernMacro(KERN,FUNC)   \
switch(KERN) {                       \
case 1: FUNC(1);                     \
case 2: FUNC(2);                     \
case 3: FUNC(3);                     \
/* ... */                            \
}

そのような

void A::FuncA(int i, double x) const
{
#define FuncK(KERN) return func_a<KERN>(i,x);
  SwitchKernMacro(Kern,FuncK);
#undef FuncK
}

関数の実装が単純 (または同様) になるように、この C マクロを避けて可変個引数テンプレート ソリューションを使用するのが好きです。

void A::FuncA(int i, double x) const
{ return SwitchKern(Kern,func_a,i,x); }    
void A::FuncB(double a, double b, char c) const
{ return SwitchKern(Kern,func_b,a,b,c); }
unsigned A::FuncC(float f, std::vector<int> const&v) const
{ return SwitchKern(Kern,func_c,f,v); }

テンプレートはSwitchKernどのように表示されますか?

編集

C++ テンプレートと、それらをいつ使用できるかについて、いくつかの混乱があるようです。次の非常に単純な関数しかないとします。

class A {
  int Kern;
  template int> void simple() const;
public:
  void Simple() const
  {
    switch(K) {
    case 1: return simple<1>();
    case 2: return simple<2>();
    case 3: return simple<3>();
    default: return simple<0>();
    }
  }
  /* ... */
};

A::Simple()次に、経由で実装することもできます

class A {
  /* ... */
  template<int> friend struct simple_aux;
};

template<class T, template<int> class SimpleAux>
void Switch(int K, const T* a) {
  switch(K) {
  case 1: return SimpleAux<1>(a)();
  case 2: return SimpleAux<2>(a)();
  case 3: return SimpleAux<3>(a)();
  default: return SimpleAux<0>(a)();
  }
}

template<int k> struct simple_aux
{
  const A*const a;
  explicit simple_aux(const A*a__) : a(a__) {}
  void operator()() { return a->simple<k>(); }
};

void A::Simple() const
{ Switch<A,simple_aux>(K,this); }

voidただし、このソリューションでは、関数への任意の引数A::Simple()( に渡される) とは異なる戻り値の型は許可されませんA::simple<>()。私の質問は、可変個引数テンプレートを使用してこれらの機能を追加する方法でした

4

2 に答える 2

3

問題は、関数テンプレートをテンプレートに渡すことができず、クラス テンプレートのみを渡すことです。これは、ヘルパー クラスを使用して回避できます。

template<template<int i> class Helper, typename... Args>
auto SwitchKern(int Kern, const A &a, Args &&...args)
-> decltype((a.*(Helper<0>::func()))(args...))
{
    switch (Kern) {
    case 1: return (a.*(Helper<1>::func()))(std::forward<Args>(args)...);
    case 2: return (a.*(Helper<2>::func()))(std::forward<Args>(args)...);
    case 3: return (a.*(Helper<3>::func()))(std::forward<Args>(args)...);
    }
}

template<int i>
struct FuncAHelper {
    static decltype(&A::func_a<i>) func() { return &A::func_a<i>; }
};

void A::FuncA(int i, double x) const
{
    return SwitchKern<FuncAHelper, int &, double &>(Kern, *this, i, x);
}

関数テンプレートをポリモーフィック関数オブジェクトに適応させる一般的な方法はありますか?も参照してください。

于 2012-09-25T16:34:36.860 に答える
-1

テンプレートはすべてコンパイル時のソリューションに関するものであり、実行時の問題を解決するのに役立つとは思わないため、スイッチを使用してランタイム値をチェックしている場合、テンプレート (可変長または通常) に変更することはできません。

于 2012-09-25T16:16:36.733 に答える