Editar: La respuesta corta a mi pregunta es que tuve una visión equivocada de lo que SFINAE puede hacer y no se compruebe el cuerpo de la función en absoluto: does sfinae instantiates a function body?¿Hay alguna manera de detectar si una función existe y se puede usar en tiempo de compilación?
Tengo un problema similar a éste: Is it possible to write a template to check for a function's existence?
La diferencia es que no solo quiero verificar si la función existe, sino también quiero saber si pasará SFINAE. Aquí está un ejemplo de lo que estoy tratando de lograr:
struct A
{
void FuncA() { std::cout << "A::FuncA" << std::endl; }
};
struct B
{
void FuncA() { std::cout << "B::FuncA" << std::endl; }
void FuncB() { std::cout << "B::FuncB" << std::endl; }
};
template<typename T>
struct Inter
{
void FuncA() { t.FuncA(); }
void FuncB() { t.FuncB(); }
T t;
};
// Always takes some sort of Inter<T>.
template<typename InterType>
struct Final
{
void CallFuncs()
{
// if(t.FuncA() exists and can be called)
t.FuncA();
// if(t.FuncB() exists and can be called)
t.FuncB();
}
InterType t;
};
void DoEverything()
{
Final<Inter<A>> finalA;
Final<Inter<B>> finalB;
finalA.CallFuncs();
finalB.CallFuncs();
}
Nótese que en CallFuncs(), tanto funcA() y FuncB() siempre va a existir, pero no podrá recopilar dependiendo del tipo T utilizado en Inter. Cuando traté de usar la respuesta en la pregunta vinculada anterior, parecía darme siempre la verdad, lo que supongo es porque solo está comprobando que la función existe, no que realmente se pueda compilar (aunque no puedo descartar que yo no modifica algo ...)
con el fin de llamar condicionalmente las funciones Calculo que puedo utilizar enable_if como tal:
template<typename InterType>
typename std::enable_if< ! /* how to determine if FuncA can be called? */>::type TryCallFuncA(InterType& i)
{
}
template<typename InterType>
typename std::enable_if</* how to determine if FuncA can be called? */>::type TryCallFuncA(InterType& i)
{
i.FuncA();
}
template<typename InterType>
typename std::enable_if< ! /* how to determine if FuncB can be called? */>::type TryCallFuncB(InterType& i)
{
}
template<typename InterType>
typename std::enable_if</* how to determine if FuncB can be called? */>::type TryCallFuncB(InterType& i)
{
i.FuncB();
}
template<typename InterType>
struct Final
{
void CallFuncs()
{
TryCallFuncA(t);
TryCallFuncB(t);
}
InterType t;
};
pero no estoy seguro si hay cualquier manera que pueda obtener un valor booleano para pasar a enable_if. ¿Hay alguna forma de que pueda lograr esto o necesito recurrir a algún tipo de rasgos de tipo mantenidos manualmente que indiquen si las funciones existen?
Por lo que vale la pena en cuanto a la disposición C++ conjunto 11 de función, estoy usando MSVC 2010.
edición: Para añadir una nota importante, en mi situación real de la implementación de la clase Inter es efectivamente opaco en el punto donde necesito determinar si Inter :: FuncA/FuncB se compilará o no, así que no puedo simplemente crear los tipos secundarios y verificar la existencia de la función en ellos.
Si no recuerdo mal, existe un problema con las plantillas de argumentos y funciones por defecto en C++ 03 que harían que esta solución solo esté disponible en C++ 11. ¿Podrías confirmar/enfermar? –
@MatthieuM .: Correcto, esta es una solución única de C++ 11. En C++ no puede proporcionar el argumento predeterminado para la plantilla de función. Esta es una característica muy buena que ha escapado al radar en el nuevo estándar y es necesaria en muchos casos donde el estándar exige que una función particular * no participe en la resolución de sobrecarga a menos que X sea verdadera. * (Es decir, SFINAE obligatoria). –
Desafortunadamente eso no es compatible con VS (2010 o 2012). A los efectos de comprender la solución, el argumento predeterminado & U :: FuncA no solo se comprueba que existe, sino también que si se llama se compilará correctamente (por ejemplo, el tipo proporcionado para Inter podría ser una clase de plantilla (por ejemplo, estructura A ) y la implementación de FuncA/FuncB depende de ese tipo)? –
Screndib