En C++ 11 la más corta solución más general que encontré fue ésta:
#include <type_traits>
template<class T, class = decltype(std::declval<T>() < std::declval<T>())>
std::true_type supports_less_than_test(const T&);
std::false_type supports_less_than_test(...);
template<class T> using supports_less_than = decltype(supports_less_than_test(std::declval<T>()));
#include<iostream>
struct random_type{};
int main(){
std::cout << supports_less_than<double>::value << std::endl; // prints '1'
std::cout << supports_less_than<int>::value << std::endl; // prints '1'
std::cout << supports_less_than<random_type>::value << std::endl; // prints '0'
}
Works con g++ 4.8.1
y clang++ 3.3
una solución más general para los operadores arbitrarios (ACTUALIZACIÓN 2014)
Hay una solución más general que explota el hecho de que todos los edificios Los operadores t-in también son accesibles (y posiblemente especializados) a través de contenedores de operador STD, como std::less
(binario) o std::negate
(unario).
template<class F, class... T, typename = decltype(std::declval<F>()(std::declval<T>()...))>
std::true_type supports_test(const F&, const T&...);
std::false_type supports_test(...);
template<class> struct supports;
template<class F, class... T> struct supports<F(T...)>
: decltype(supports_test(std::declval<F>(), std::declval<T>()...)){};
Esto se puede utilizar de una manera muy general, especialmente en C++ 14, donde el tipo de deducción se retrasa a la llamada envoltura operador ("operadores transparentes").
Para los operadores binarios que puede ser utilizado como:
#include<iostream>
struct random_type{};
int main(){
std::cout << supports<std::less<>(double, double)>::value << std::endl; // '1'
std::cout << supports<std::less<>(int, int)>::value << std::endl; // '1'
std::cout << supports<std::less<>(random_type, random_type)>::value << std::endl; // '0'
}
Para los operadores unarios:
#include<iostream>
struct random_type{};
int main(){
std::cout << supports<std::negate<>(double)>::value << std::endl; // '1'
std::cout << supports<std::negate<>(int)>::value << std::endl; // '1'
std::cout << supports<std::negate<>(random_type)>::value << std::endl; // '0'
}
(Con la biblioteca estándar de C++ 11 es un poco más complicado porque no hay fracaso al instalar decltype(std::less<random_type>()(...))
, incluso si no hay una operación definida para random_type
, se pueden implementar operadores transparentes manualmente en C++ 11, que son estándar en C++ 14)
La sintaxis es bastante fluida. Espero que algo así se adopte en el estándar.
Dos extensiones:
1) Se trabaja para detectar aplicaciones-función en bruto:
struct random_type{};
random_type fun(random_type x){return x;}
int main(){
std::cout << supports<decltype(&fun)(double)>::value << std::endl; // '0'
std::cout << supports<decltype(&fun)(int)>::value << std::endl; // '0'
std::cout << supports<decltype(&fun)(random_type)>::value << std::endl; // '1'
}
2) que puede detectar, además, si el resultado es convertible/comparable a un cierto tipo, en este caso es compatible con double < double
, pero se devolverá un tiempo de compilación falso porque el resultado no es el especificado.
std::cout << supports<std::equal_to<>(std::result_of<std::less<>(double, double)>::type, random_type)>::value << std::endl; // '0'
Nota: Me acaba de intentar compilar el código C++ con 14 en http://melpon.org/wandbox/ y no funcionó. Creo que hay un problema con los operadores transparentes (como std::less<>
) en esa implementación (clang ++ 3.5 C++ 14), ya que cuando implemente mi propio less<>
con deducción automática, funciona bien.
No necesitamos usar 'C++ 0x' para comprobar si existe la función' operator <'en la clase. Podemos simplemente personalizar esa función para la sobrecarga genérica y usar su tamaño para la lógica negativa. Ver mi respuesta a continuación. – iammilind
Para aquellos que buscan una solución portátil preempaquetada para esto, hay 'plantilla struct has_less: public true_type-or-false_type {};' in '#include '. Documentación: http://www.boost.org/doc/libs/1_56_0/libs/type_traits/doc/html/boost_typetraits/reference/has_less.html –
alfC