Este problema se basa en el código que funciona para mí en GCC-4.6 pero no para otro usuario con CLang-3.0, ambos en modo C++ 0x.Conflicto entre el constructor de copia y el constructor de reenvío
template <typename T>
struct MyBase
{
//protected:
T m;
template <typename Args...>
MyBase(Args&& ...x) : m(std::forward<Args>(x)...) {}
};
Un objeto de MyBase
puede tomar cualquier lista de argumentos del constructor, siempre y cuando T
admite que la firma de la construcción. El problema tiene que ver con las funciones de miembros especiales.
- IIUC, la plantilla del constructor cancela el constructor predeterminado definido automáticamente. Sin embargo, dado que la plantilla puede aceptar cero argumentos, actuará como un constructor predeterminado explícitamente definido (siempre que
T
sea predeterminado-construible). - IIUC, determinación de una política de copia de construcción de clase ignora las plantillas de constructor. Esto significa que en este caso
MyBase
ganará un constructor de copias definido automáticamente (siempre que se pueda copiarT
) que tendrá el canalT
copy-construction. - También aplique el paso anterior para la construcción de movimientos.
Así que si paso un MyBase<T> const &
como el único argumento del constructor, que el constructor es llamada, la expedición o la implícita una copia?
typedef std::vector<Int> int_vector;
typedef MyBase<int_vector> VB_type;
int_vector a{ 1, 3, 5 };
VB_type b{ a };
VB_type c{ b }; // which constructor gets called
El problema de mi usuario fue utilizar esto como una clase base. El compilador se quejó de que su clase no podía sintetizar un constructor de copia definido automáticamente, porque no podía encontrar una coincidencia con la plantilla de constructor de la clase base. ¿No debería llamar al MyBase
copia-constructor automático para su propio copia-constructor automático? ¿Es CLang un error por tener un conflicto?
Interesante pregunta. Recomiendo hacer una sscce (ver http://sscce.org/) que funcione en GCC y fallar en CLang para ayudarnos a entender mejor el problema y recrearlo nosotros mismos. Además, envíenos el mensaje de error exacto de CLang. –
En realidad, una versión de gcc relativamente cerca de la cabeza (a partir de 20120202) tampoco acepta este código. Parece que el constructor de reenvío está siendo recogido incluso para la copia. No estoy muy seguro de por qué esto. No está relacionado con la "sintaxis de inicialización uniforme": incluso cuando se usa paréntesis para la última declaración, no se compila. –
Mi código es algo que escribí hace una década para Boost y que se actualizó para C++ 11 la semana pasada. No sé cómo trabajar con todo el sistema Trac de Boost, pero puede consultar [mis cambios] (https://svn.boost.org/trac/boost/changeset/76982) y el [estado actual] (http : //svn.boost.org/svn/boost/trunk/boost/utility/base_from_member.hpp) del archivo (en la revisión 77031 al momento de escribir este documento). – CTMacUser