Plantillas variádicas de C++
Estoy usando una definición de vector:
vector<lmlink_out> os{
lmlink_out(typeid(string &)),
lmlink_out(),
lmlink_out(typeid(int),typeid(char))
};
usando el siguiente código funciona (definido dentro de la clase):
class lmlink_out {
vector<const type_info*> parameters;
…
public:
template<typename… T, std::size_t N = sizeof…(T)>
lmlink_out(const T&… args) : parameters({&args…}) {}
usar esto otro da lugar a un error de compilación (definido fuera de la clase):
class lmlink_out {
vector<const type_info*> parameters;
…
public:
template<typename… T, std::size_t N = sizeof…(T)>
lmlink_out(const T&… args);
};
- template<typename… T, std::size_t N = sizeof…(T)>
- lmlink_out::lmlink_out(const T&… args)
- parameters({(&args…})
{
}
el compilador (versión gcc 10.2.1 20210110 (Debian 10.2.1-6)) devuelve:
- error: no se encontró una función coincidente para llamar a ‘std::vector<const
- std::typeinfo*>::vector(
)’ 374 | - parameters({(&args…}) nota: el candidato es: ‘std::vector<Tp,
Alloc>::vector(std::initializerlist<Tp>, const allocatortype&) [con Tp = const std::typeinfo; _Alloc = std::allocator>; std::vector<Tp, _Alloc>::allocatortype = list<valuetype> _l,
std::allocatorinfo*>]’ 625 |
vector(initializer
…
| ^~~~~~ /usr/include/c++/10/bits/stlvector.h:625:43: nota: no hay una conversión conocida para el argumento 1 de ‘’ a ‘std::initializer list’
Creo que los dos códigos son semánticamente equivalentes, ¿por qué el segundo da un error?
Necesito agregar otro constructor:
template<typename… T, std::size_t N = sizeof…(T)>
lmlink_out(const string &name, const T&… args) : name(name), parameters({&args…}) {}
pero da lugar al mismo error mencionado anteriormente.
davy.ai
La razón por la cual el segundo código da lugar a un error de compilación es que la sintaxis para utilizar una expansión de paquete de parámetros dentro de una lista de inicializadores delimitada por llaves no está permitida fuera de una clase o función de plantilla. El compilador no puede deducir los tipos de la expansión del paquete de parámetros y, por lo tanto, no puede construir el vector.
Para solucionar el error, puedes mantener la definición del constructor dentro de la clase o utilizar una función separada para construir el vector. Por ejemplo:
Aquí, definimos una función privada
make_vector
que construye el vector utilizando una expansión de paquete de parámetros dentro de una lista de inicializadores delimitada por llaves. El constructorlmlink_out
llama a esta función para inicializar el miembroparameters
.De esta manera, el código se compilará sin errores y podrás agregar el nuevo constructor con un parámetro de tipo string y una expansión de paquete de parámetros para inicializar el miembro
parameters
de la misma manera que el constructor original.</typename…></typename…>