Lo siento por usted engañosa en la última respuesta, pensé por un momento que sería más sencillo. Entonces intentaré proporcionar una solución completa aquí. El enfoque general para resolver este tipo de problemas es escribir una plantilla rasgos ayudante y utilizarlo junto con enable_if
(ya sea C++ 11, impulso o aplicación manual) para decidir una especialización de clase:
Rasgo
Un enfoque simple, no necesariamente la mejor, pero fácil de escribir sería:
template <typename T>
struct has_nested_Vec {
typedef char yes;
typedef char (&no)[2];
template <typename U>
static yes test(typename U::Vec* p);
template <typename U>
static no test(...);
static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};
el enfoque es simple, proporciona dos funciones de plantilla, que los tipos de retorno de diferentes tamaños. Uno de los cuales toma el tipo anidado Vec
y el otro toma puntos suspensivos. Para todos los tipos que tienen un Vec
anidado, la primera sobrecarga es una mejor coincidencia (la elipsis es la peor coincidencia para cualquier tipo). Para aquellos tipos que no tienen un Vec
anidado, SFINAE descartará esa sobrecarga y la única opción que queda será la elipsis. Entonces ahora tenemos un rasgo para preguntar si cualquier tipo tiene un tipo anidado Vec
.
enable Si
Se puede usar esta de cualquier biblioteca, o se puede liar, es bastante simple:
template <bool state, typename T = void>
struct enable_if {};
template <typename T>
struct enable_if<true,T> {
typedef T type;
};
Cuando el primer argumento es false
, la plantilla base es la única opción, y que no tiene un type
anidado, si la condición es true
, entonces enable_if
tiene un type
anidado que podemos usar con SFINAE.
Implementación
Ahora necesitamos proveer la plantilla y la especialización que va a utilizar SFINAE sólo para aquellos tipos con un anidado Vec
:
template<class T, class V = void>
struct Functor {
void operator()() const {
std::cerr << "general" << std::endl;
}
};
template<class T>
struct Functor<T, typename enable_if<has_nested_Vec<T>::value>::type > {
void operator()() const {
std::cerr << "special" << std::endl;
}
};
Cada vez que creamos una instancia Functor
con un tipo, el el compilador intentará usar la especialización, que a su vez instanciará has_nested_Vec
y obtendrá un valor de verdad, pasado a enable_if
. Para aquellos tipos cuyo valor es false
, enable_if
no tiene un tipo anidado type
, por lo que la especialización se descartará en SFINAE y se utilizará la plantilla base.
su caso particular
En su caso particular, en el que parece que realmente no necesita especializarse todo tipo, pero sólo el operador, se pueden mezclar los tres elementos en uno solo: una Functor
que despacha a una de las dos funciones con plantilla interna en base a la presencia de Vec
, eliminando la necesidad de enable_if
y la clase rasgos:
template <typename T>
class Functor {
template <typename U>
void op_impl(typename U::Vec* p) const {
std::cout << "specialized";
}
template <typename U>
void op_impl(...) const {
std::cout << "general";
}
public:
void operator()() const {
op_impl<T>(0);
}
};
Se ha eliminado la etiqueta 'compiler', generalmente se utiliza para la pregunta sobre el proceso de compilación en sí, mientras que esta pregunta es sobre el lenguaje C++. –