Как запрограммировать это с помощью шаблонов?

Я никогда не использовал вариационные шаблоны сам, но думаю, что они могут понадобиться мне сейчас. Предположим, у меня есть класс

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

где определения 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<>()). Мой вопрос был о том, как добавить эти функции с помощью шаблонов

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

Смотрите также Есть ли общий способ приспособить шаблон функции к объекту полиморфной функции?

3

Другие решения

Я думаю, что шаблоны все о решениях времени компиляции, и они не могут помочь решить проблемы времени выполнения, поэтому, если вы используете переключатель для проверки значения времени выполнения, вы не можете изменить его на шаблон (либо переменный, либо обычный).

-1

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector