¿Cuál es la mejor manera de renombrar(alias/reenviar) una función en C++?
templates c++11 (1)
(Limitaré esta pregunta a C ++ 11, ya que creo que no hay una forma general de hacerlo en C ++ 98).
Supongo que tengo un conjunto complicado (en términos de firma) de funciones de plantilla y / o funciones sobrecargadas, y quiero usar estas funciones exactamente de la misma manera pero usando un nombre diferente (es decir, un alias).
Por ejemplo:
template<class A, class B, class C>
D fun(A a, B& b, C&& c){ ... }
template<class E, class F>
G fun(H<E> he, F& f){ ... }
... many other versions of fun
Ahora suponga que quiero cambiar el nombre (o alias , o reenviar para que sea más preciso) estas funciones, todas a la vez (es decir, poder usar un nombre diferente para la misma función sin volver a escribirla). De tal manera, en otras partes del código puedo usarlo con un nombre diferente y sin modificar el código anterior.
¿Es esta la forma correcta de cambiar el nombre (alias / adelante) fun
convertirla en gun
?
template<typename... Args>
inline auto gun(Args&&... args)->decltype(fun(std::forward<Args>(args)...)){
return fun(std::forward<Args>(args)...);
}
- ¿Es realmente general?
- ¿Es esta la forma más sencilla?
- ¿Es esta la manera óptima? (por ejemplo, puede estar en línea, sin copias innecesarias)
- ¿Qué pasa si la función original tenía algunas características de SFINAE? (por ejemplo, la
template<class A, class B, class C, class = std::enable_if< ... >::type>
), ¿transferirá Decltype el SFINAE en todos los casos? - ¿Qué pasa si la función original devuelve referencias? ¿No va a quitar el tipo de referencia el tipo de referencia? (por ejemplo,
double& fun(double& x){return x;}
). - ¿Se puede decir lo mismo de las funciones de los miembros?
Aclaración: la gun
nunca va a ser exactamente fun
, ya que las instancias tendrán diferentes direcciones, pero lo que busco es un cambio de nombre para el punto de vista de la codificación genérica.
Comentario: Me parece extraño que casi todo pueda ser renombrado / reenviado, espacios de nombres, tipos ( typedef
) y tipos de plantillas using typedef
, pero no funciones (o, para el caso, funciones miembro).
EDITAR : Para completar, y ya que esta parece ser la manera de hacerlo, aquí agregué una macro para definir alias de funciones:
#define ALIAS_FUNCTION(OriginalnamE, AliasnamE) /
template <typename... Args> /
inline auto AliasnamE(Args&&... args) -> decltype(OriginalnamE(std::forward<Args>(args)...)) { /
return OriginalnamE(std::forward<Args>(args)...); /
}
y luego lo usas así:
namespace NS1{namepsace NS2{
ALIAS_FUNCTION(NSA::fun, gun); // second argument (target name can''t have namespace)
}}
¿Es realmente general?
Sí.
¿Es esta la forma más sencilla?
Sí (tristemente).
¿Es esta la manera óptima? (por ejemplo, puede estar en línea, sin copias innecesarias)
Sí.
¿Qué pasa si la función original tenía algunas características de SFINAE? (por ejemplo, la
template<class A, class B, class C, class = std::enable_if< ... >::type>
), ¿transferirá Decltype el SFINAE en todos los casos?
Sí, si la expresión dentro de decltype
produce un error (es decir, la fun
no existe, tal vez debido a SFINAE en la fun
), esto activará SFINAE para la gun
también, eliminándola del conjunto de sobrecarga.
¿Qué pasa si la función original devuelve referencias? ¿No va a quitar el tipo de referencia el tipo de referencia? (por ejemplo,
double& fun(double& x){return x;}
).
No, ¿por qué?
Lo mismo se puede decir acerca de las funciones miembro, aunque esto se debe hacer modificando la clase, supongo.
Esto no es una pregunta. ¿Qué se puede decir acerca de las funciones de los miembros? Todo lo anterior se aplica igualmente.