c++ - valores - variable independiente funcion
(Parcialmente) especializando un parĂ¡metro de plantilla sin tipo de tipo dependiente (4)
Tal vez estoy cansado, pero estoy atascado con esta especialización parcial simple, que no funciona porque el non-type template argument specializes a template parameter with dependent type ''T''
:
template <typename T, T N> struct X;
template <typename T> struct X <T, 0>;
Reemplazar 0
por T(0)
, T{0}
o (T)0
no ayuda. Entonces, ¿esta especialización es posible?
Necesita pasar un valor integral en una plantilla. Ambos, su primera y segunda plantilla, no funcionarán si el tipo T no es de tipo integral.
Puede pasar rasgos como un parámetro de plantilla tipada para especificar el valor N:
#include <iostream>
// error: ‘double’ is not a valid type for a template non-type parameter
template <typename T, T N> struct X0;
// error: ‘double’ is not a valid type for a template non-type parameter
template <typename T, T N, int = 0> struct X1;
template <typename T, T N>
struct IntegralTraits {
static constexpr T Value() { return N; }
};
template <typename T, typename Traits = void>
struct X2 {
static constexpr T Value() { return Traits::Value(); }
};
template <typename T>
struct X2<T, void> {
static constexpr T Value() { return T(); }
};
int main() {
// error: ‘double’ is not a valid type for a template non-type parameter
// X0<double, 0>();
// error: ‘double’ is not a valid type for a template non-type parameter
// X1<double, 0>();
X2<int> a;
X2<double, IntegralTraits<int, 1>> b;
std::cout.precision(2);
std::cout << std::fixed << a.Value() << ", "<< b.Value() << ''/n'';
return 0;
}
Si se limita a tipos integrales, elija uno grande:
template <typename T, std::size_t N = 0> struct X {};
Puede agregar un parámetro typename=void
al final de la lista de argumentos de la template
, luego vaya hog wild con std::enable_if_t<
condición >
en especializaciones.
Solución usando la solución de Yakk:
#include <iostream>
#include <type_traits>
template <typename T, T N, typename = void >
struct X {
static const bool isZero = false;
};
template <typename T, T N>
struct X < T, N, typename std::enable_if<N == 0>::type > {
static const bool isZero = true;
};
int main(int argc, char* argv[]) {
std::cout << X <int, 0>::isZero << std::endl;
std::cout << X <int, 1>::isZero << std::endl;
return 0;
}
Ver el párrafo [temp.class.spec] 14.5.5 / 8 del estándar:
El tipo de un parámetro de plantilla correspondiente a un argumento especializado sin tipo no dependerá de un parámetro de la especialización. [ Ejemplo:
template <class T, T t> struct C {}; template <class T> struct C<T, 1>; // error template< int X, int (*array_ptr)[X] > class A {}; int array[5]; template< int X > class A<X,&array> { }; // error
-Final ejemplo ]
La respuesta a su edición: la solución más fácil es reemplazar un parámetro de plantilla sin tipo con uno de tipo:
#include <type_traits>
template <typename T, typename U>
struct X_;
template <typename T, T N>
struct X_<T, std::integral_constant<T, N>> {};
template <typename T>
struct X_<T, std::integral_constant<T, 0>> {};
template <typename T, T N>
struct X : X_<T, std::integral_constant<T, N>> {};