c++ templates visual-studio-2012 c++11 static-assert

c++ - ¿Cómo restrinjo una clase de plantilla a ciertos tipos incorporados?



templates visual-studio-2012 (3)

De esta manera, también permite la especialización para varios tipos:

template<typename T, typename Enable = void> class A { /// Maybe no code here or static_assert(false, "nice message"); }; /// This specialization is only enabled for double or float. template<typename T> class A<T, typename enable_if<is_same<T, double>::value || is_same<T, float>::value>::type> { };

Este problema se ha discutido varias veces, pero todas las soluciones que he encontrado no funcionaron o se basaron en la afirmación estática de boost. Mi problema es simple Tengo una clase, y solo quiero permitir tipos reales (doble y flotante). Quiero un error en tiempo de compilación si intento crear una instancia de la clase con un tipo que no sea float o double. Estoy usando Visual C ++ 11. Esto es lo que he intentado:

template <typename RealType> class A { // Warning C4346 static_assert(std::is_same<RealType, double>::value || std::is_same<RealType, float>::value); } template <typename RealType> class A { // Error C2062: type ''unknown'' unexpected static_assert(decltype(RealType) == double || decltype(RealType) == float); }

¿Algunas ideas? ¡Gracias por adelantado!


Una solución que he visto es usar std::enable_if en un alias tipo. Algo como:

using value_type = typename std::enable_if< std::is_same<float, RealType>::value || std::is_same<double, RealType>::value, RealType >::type;

value_type solo existe si RealType es exactamente float o double . De lo contrario, el tipo no está definido y la compilación falla.

Sin embargo, advertiría sobre ser demasiado estricto con los tipos. Las plantillas son tan poderosas como lo son en parte porque la tipificación de pato que hacen significa que cualquier tipo que se pueda usar de la manera que desee usarlo, funcionará. Denegar tipos por el simple hecho de rechazar tipos generalmente no te ayuda mucho y puede hacer que las cosas sean menos flexibles de lo que podrían ser. Por ejemplo, no podría usar un tipo con más precisión, como un tipo de gran decimal.


En su primer ejemplo, static_assert debería tomar un segundo parámetro que sería un literal de cadena, de lo contrario se considera que falla ( editar: dejar caer el segundo parámetro es legal desde C ++ 17). Y este segundo argumento no puede ser incumplido.

Su segundo ejemplo es incorrecto por varias razones:

  • decltype se debe usar en una expresión, no en un tipo.
  • Simplemente no puede comparar tipos con == , la forma correcta de hacerlo es lo que intenta en su primer intento con std::is_same .

Entonces, la forma correcta de hacer lo que estás tratando de lograr es:

#include <type_traits> template <typename RealType> class A { static_assert(std::is_same<RealType, double>::value || std::is_same<RealType, float>::value, "some meaningful error message"); };

Además, apuesto a que estás tratando de restringir tu plantilla a valores de puntos flotantes. Para hacer esto, puede usar el rasgo std::is_floating_point :

#include <type_traits> template <typename RealType> class A { static_assert(std::is_floating_point<RealType>::value, "class A can only be instantiated with floating point types"); };

Y como un extra, toma este ejemplo en línea .