/ / Especialización de plantillas con múltiples plantillas variadic - c ++, templates, c ++ 11, typetraits

Especialización de plantillas con múltiples plantillas variadas - c ++, templates, c ++ 11, typetraits

En mi última pregunta Recibí una gran ayuda para hacer que una especialización de plantillas funcionara. Ahora necesito una pequeña extensión. Quiero dos especializaciones para estas declaraciones:

int main()
{
// First specialization
holder_ext<person> h1;
holder_ext<person, &person::age> h2;
holder_ext<int> h3;

// Second specialization
holder_ext<person, &person::age, &person::name> h4;
}

Mi persona de clase se ve así:

class person
{
private:
std::string name_;
int age_;
public:
person(const std::string &name)
: name_(name), age_(56)
{}
void age(int a) { age_ = i; }
void name(const std::string &n) { name_ = n; }
};

Lo especial es que los dos miembros.Las funciones tienen diferentes tipos de parámetros. Así que no puedo usar la misma función de miembro de la plantilla variadic para ambos. Lo probé con dos plantillas variadic diferentes. Pero eso no funciona. También los valores predeterminados para las funciones miembro no funcionan.

¿Alguien tiene una buena pista para mí?

Esta es la solución con una función miembro (gracias a Pubby)

template < class T, void (std::conditional<std::is_class<T>::value, T, struct dummy>::type::* ...FUNC)(int)> class holder;

template < class T, void (T::*FUNC)(int)>
class holder<T, FUNC>
{
public:
explicit holder() : setter(FUNC) { std::cout << "funcn"; }
private:
std::function<void (value_type&, int)> setter;
};

template < class T>
class holder<T>
{
public:
explicit holder() { std::cout << "plainn"; }
};

Gracias de nuevo por adelantado!

P.S .: Y no, no voy a aparecer en dos días con "¿qué debo hacer con tres, cuatro, cinco funciones de miembro"? ;-)

Respuestas

0 para la respuesta № 1

Para una solución totalmente genérica estaría golpeandoun problema que no se puede resolver: el tipo de argumento de plantilla que no es de tipo no se puede inferir, por lo que debe ser explícito en la declaración de la plantilla, por lo que no hay forma de decirle a la plantilla que desea múltiples argumentos de puntero a miembro cada uno que tendrá un tipo aún desconocido.

No he jugado con C ++ 11 lo suficiente, pero podría intentar forzar un orden en los argumentos de la plantilla de miembro y proporcionar todas las firmas en la plantilla:

template <typename T,
void (std::conditional<...>::type*)(int),
void (std::conditional<...>::type*)(const std::string&)>

Una vez más, podría funcionar o podría no ...


0 para la respuesta № 2

Finalmente encontré una solución para mi problema. Es una mezcla de plantillas variadas y especificación de plantillas:

template < class T,
void (std::conditional<std::is_base_of<object, T>::value, T, struct dummy>::type::*FUNC1)(int) = nullptr,
void (std::conditional<std::is_base_of<object, T>::value, T, struct dummy>::type::* ...FUNC2)(const std::string&)
>
class holder_ext;

template < class T,
void (std::conditional<std::is_base_of<object, T>::value, T, struct dummy>::type::*FUNC1)(int),
void (std::conditional<std::is_base_of<object, T>::value, T, struct dummy>::type::*FUNC2)(const std::string&)
>
class holder_ext<T, FUNC1, FUNC2>
{
public:
holder_ext() { std::cout << "func 2 testn"; }
};

template < class T,
void (std::conditional<std::is_base_of<object, T>::value, T, struct dummy>::type::*FUNC1)(int)
>
class holder_ext<T, FUNC1>
{
public:
holder_ext() { std::cout << "func 1 testn"; }
};

Utilizo una declaración no implementada y defino dos especializaciones. Uno con la función miembro y el otro para todos los demás casos.

Si hay una solución mejor, no dude en decírmelo.