Si tenemos una metafunción de plantilla como std::conditional
, podemos “seleccionar” tipos basados en una condición de tiempo de comstackción booleana. Por ejemplo:
template struct conditional; template struct conditional { using type = T; }; template struct conditional { using type = U; }; const bool whats_big = sizeof( int ) > sizeof( double ); using bigger_type = typename conditional::type;
Mi pregunta es: ¿hay alguna forma de seleccionar entre un tipo válido y un tipo no válido?
Actualmente estoy implementando una clase de evento. Los eventos tienen un parámetro de remitente y un número variable de eventos args:
template class event;
Por lo tanto, las funciones con tipo void(SENDER& , ARGS&...)
podrían usarse como controladores de eventos. En ese caso, se llama a los manejadores pasando una referencia al objeto que ha generado el evento (Threas the sender param).
Por otro lado, quiero una manera de permitir que las funciones de miembro remitente sean manejadores de eventos, en otras palabras, funciones de tipo void(SENDER::*)(ARGS&...)
.
El problema es que no puedo usar una oración como:
using handler_type = typename conditional<std::is_class::value,void(SENDER::*)(ARGS&...) , void(SENDER& , ARGS&...)>::type;
Debido a que en el caso de que SENDER
no sea un tipo de clase, el primer tipo no es válido (utiliza un puntero a un miembro de un tipo que no es de clase).
Puedes hacerlo con un nivel extra de direccionamiento indirecto:
template struct sender_chooser { using type = void(*)(T &, Args &...); }; template struct sender_chooser { using type = void (T::*)(Args &...); }; template struct sender_type { using type = typename sender_chooser::value, T, Args...>::type; };
Uso:
sender_type::type
Esto es void (MySender::*)(Arg1 &, Arg2 &, Arg3 &)
si MySender
es un tipo de clase, o de lo contrario void (*)(Sender &, Arg1 &, Arg2 &, Arg3 &)
.
(También es posible que desee permitir los sindicatos.)