¡Yay, otro título de pregunta compuesto por una secuencia aleatoria de términos de C++!Función de conversión con plantilla para el puntero de función
Normalmente hacemos una clase invocable implementando operator()
. Pero también puede hacerlo implementando una conversión definida por el usuario a un puntero de función o tipo de referencia. En lugar de utilizar el reenvío perfecto, una función de conversión puede devolver un puntero a una función que luego se llama con la lista de argumentos original.
struct call_printf {
typedef int printf_t(char const *, ...);
operator printf_t &() { return std::printf; }
};
Por lo que yo puedo decir, la typedef
anterior es una necesidad sintáctica. El nombre de una función de conversión se forma a partir de type-specifier-seq, que no permite una construcción como int (*)()
. Eso requeriría un resumen-declarador. Presumiblemente, la razón es que tales nombres de tipos se vuelven complicados, y los constructos complejos utilizados como nombres de objetos son difíciles de analizar.
Las funciones de conversión también pueden ser modeladas, pero los argumentos de la plantilla deben deducirse, porque no hay ningún lugar para especificarlos explícitamente. (Eso acabaría con el punto central de la conversión implícita.)
Pregunta # 1: En C++ 03, es decir que no había manera de especificar una plantilla encargado de la conversión de la función? Parece que no había forma de resolver los argumentos de la plantilla (es decir, nombrarlos en un contexto deducido) en un tipo de puntero de función aceptable.
Aquí está la referencia equivalente de C++ 11, §13.3.1.1.2/2 [over.call.object]. Es sustancialmente la misma a partir de C++ 03:
Además, para cada función de conversión no explícita declarada en T de la forma
operator conversion-type-id() cv-qualifier attribute-specifier-seqopt;
donde cv-calificador es el mismo CV- calificación como, o una mayor cv-calificación que, cv, y donde conversión de tipo-id indica la “puntero a función de (P1, ..., Pn) devolver R” tipo, o el tipo "Referencia al puntero a la función de (P1, ..., P n) devolver R”, o el tipo de‘referencia a la función de (P1, ..., Pn) devolver R’, una función de llamada sustituto con la llamada función nombre único y que tiene la forma
R call-function (conversion-type-id F, P1 a1, ... ,Pn an) { return F (a1,... ,an); }
es también se considera como una función candidata. De forma similar, las funciones de llamada indirecta se agregan al conjunto de funciones candidatas para cada función de conversión no explícita declarada en una clase base de T, siempre que la función no esté oculta dentro de T por otra declaración intermedia.
Pregunta # 2: En C++ 11, puede tal conversión puede especificar mediante un argumento de plantilla por defecto? Esto es útil para SFINAE. La única diferencia aquí del ejemplo anterior es que id-conversión-conversión solo representa una referencia de función después de la instanciación, porque es un tipo dependiente (a pesar de la invarianza).Esto activa GCC y omite la plantilla de miembro.
enum { call_alternate = true; }
struct call_switch {
template< bool en = call_alternate >
operator typename std::enable_if< en, decltype(fn_1) & >::type()
{ return fn_1; }
template< bool en = ! call_alternate >
operator typename std::enable_if< en, decltype(fn_2) & >::type()
{ return fn_2; }
};
También tenemos plantillas de alias. Parece que la sustitución de alias ocurre antes de la instanciación, dado el ejemplo en §14.5.7/2, donde las declaraciones de process
entran en conflicto. En GCC 4.7, este código al menos ejemplifica la declaración, pero luego produce un extraño "candidato espera 2 argumentos, 2 proporcionado" error.
template< typename t >
using fn_t = void (&)(t);
struct talk {
template< typename t >
operator fn_t<t>() { return fn; }
};
int main() {
talk()(3);
}
Mi bondad .... –
¿Qué estás tratando de hacer? ¿Dónde puede ser útil? – Nawaz
@Nawaz cuando quiere que un operador de conversión funcione con tipos de puntero? –