una - ¿Cómo puedo crear un constructor de C++ que acepte un número variable de int?
lenguaje de programacion c variables (4)
Has actualizado tu pregunta para indicar que todo lo que necesitas es un std::integer_sequence
tiempo de compilación, lo cual es genial.
Pero solo por el bien de los futuros lectores que podrían venir aquí buscando la respuesta, también me gustaría responder a su pregunta original: "¿Es posible restringir el tipo de argumentos en un constructor variadic?"
Sí. Una forma (¿la mejor manera? No estoy seguro) es a SFINAE en un parámetro de plantilla adicional, como este:
struct X {
template<
class... TT,
class E = std::enable_if_t<(std::is_same_v<TT, int> && ...)>
>
X(TT... tt) {
// do stuff with the ints "tt..."
}
};
El && ...
es un pliegue-expresión, nuevo en C ++ 17. Si su compilador no admite expresiones de plegado, simplemente sustitúyalo por un all_of
.
¿Es posible restringir el tipo de argumentos en un constructor variadic?
Quiero poder expresarme
X x1(1,3,4);
X x2(3,4,5);
// syntax error: identifier ''Args''
class X {
template<int ... Args> X(Args...)
{
}
};
// this works but allows other types than int
class Y {
template<typename ... Args> Y(Args...)
{
}
};
editar para aclarar la intención:
Lo que quiero lograr es almacenar los datos pasados a un constructor (constantes conocidas en tiempo de compilación) en una matriz estática.
así que hay algunos otros
template<int ...values>
struct Z
{
static int data[sizeof...(values)];
};
template<int ... values>
int Z<values...>::data[sizeof...(values)] = {values...};
y en el constructor de XI me gustaría usar Z así:
class X {
template<int ... Args> X(Args...)
{
Z<Args...>::data // do stuff with data
}
};
¿Es eso posible, nuestro tengo que usar integer_sequence?
No, no puedes restringir el tipo. Puedes usar static_assert
sin embargo. Sería algo como esto:
static_assert(std::is_same<int, Args>::value ..., "have to be ints.");
static_assert
embargo, no he intentado usar una expansión en un static_assert
así. Es posible que necesites un constexpr que devuelva bool o algo así.
Puedes usar std::initializer_list
:
#include <iostream>
#include <initializer_list>
void myFunc(std::initializer_list<int> args)
{
for (int i: args) std::cout << i << ''/n'';
}
int main(){
myFunc({2,3,2});
// myFunc({2,"aaa",2}); error!
}
Ya que tienes lo siguiente:
template<int... values>
struct Z
{
static int data[ sizeof...( values ) ];
};
template <int... values>
int Z<values...>::data[ sizeof...( values ) ] = { values... };
Puede usar std::integer_sequence<>
para pasar las entradas a Z<>
:
struct X
{
template <int... values>
X( std::integer_sequence<int, values...> )
{
for ( int i{ 0 }; i < sizeof...( values ); ++i )
Z<values...>::data[ i ]; // do stuff with data
}
};
Puedes convertirte en un tipo de ayudante para que sea más fácil llamar al ctor:
template <int... values>
using int_sequence = std::integer_sequence<int, values...>;
Entonces puedes crear una instancia de tu clase así:
int main()
{
X x( int_sequence<1, 3, 5>{} );
}