J'étais sûr que la réponse à cette question était, "Jamais, jamais un modèle ne peut être le constructeur de copie." Malheureusement, je viens de passer 3 heures à comprendre pourquoi j'obtenais un avertissement sur la récursivité, je l'ai dépisté sur le constructeur de la copie, j'ai regardé le débogueur devenir fou et ne pas me laisser regarder le code récursif un '&' manquant dans un constructeur de base.MI et bug de constructeur de copie implicite (était: Sous quelles conditions un template peut-il être le constructeur de copie?)
Vous voyez, j'ai cet hôte de conception complexe basé sur des règles qui fonctionne correctement depuis un certain temps maintenant. Je suis allé sur la redéfinition de deux politiques en une et couru dans un constructeur de copie récursive. Réduit à une politique qui est nécessaire pour fournir un constructeur qui peut prendre un type de concept XXX comme argument, mais dans ce cas, je suis juste en train de le rejeter. Alors, je l'ai écrit
struct my_policy
{
template < typename T >
my_polity(T const) {} // missing '&'...oops
};
Maintenant, my_policy est une classe de base à l'hôte (bien sûr) et cette petite faute de frappe causé récursion où le constructeur de copie de l'hôte lui-même passé la chaîne à cela, le constructeur basé sur un modèle plutôt qu'un implicite, constructeur de copie généré par le compilateur. Il faudrait alors rappeler son constructeur de copie pour créer le temporaire. La chose vraiment fascinante est que je ne peux pas recréer ceci en code simplifié. Même avec une sorte d'exemple d'hôte de politique factice, je ne peux pas y arriver. Le code suivant ne présente pas la question:
#include <boost/utility/enable_if.hpp>
#include <boost/mpl/bool.hpp>
struct base
{
template < typename T >
base(T const) {}
};
struct another_base
{
int x;
another_base(int y) : x(y) {}
};
template < typename T >
struct is_derived : boost::mpl::false_ {};
template < typename T1, typename T2 >
struct derived : T1, T2
{
template < typename T >
derived(T const& x, typename boost::disable_if< is_derived<T> >::type * = 0) : T1(0), T2(x) {}
};
template < typename T1, typename T2 >
struct is_derived<derived<T1,T2>> : boost::mpl::true_ {};
int main()
{
derived<base, another_base> d(23);
derived<base, another_base> x = d;
}
J'utilise la bibliothèque de paramètres de boost pour faire 7 ou si des arguments à l'hôte accessible par « nom ». Peut-être que c'est le problème, je ne sais pas. Quoi qu'il en soit, je me demande si quelqu'un sait quelles conditions spécifiques, le cas échéant, pourraient amener un compilateur à utiliser légitimement le constructeur basé sur un modèle pour "base" en tant que constructeur de copie ou du constructeur de copie implicite pour "derived".
Modifier la note:
Je recréée le problème dans le code ci-dessus en donnant « another_base » un constructeur de copie explicite:
struct another_base
{
int x;
another_base(another_base const& b) : x(b.x) {}
another_base(int y) : x(y) {}
};
À partir de conclure que c'est un bug du compilateur à moins que quelqu'un peut Dites-moi pourquoi c'est légitime.
Plus d'informations:
struct derived;
struct base
{
base() {}
private:
base(derived const&);
};
struct base2
{
base2() {}
//base2 (base2 const&) {}
};
struct derived : base, base2 {};
int main()
{
derived d1; derived d2(d1);
}
En regardant de plus à la réponse de Schaub je pris le code ci-dessus et compilé. Il compile juste bien jusqu'à ce que vous décommentez la déclaration du constructeur de copie de base2. Ensuite, il va exploser de la façon dont je suppose qu'il était attendu avec le code d'origine (pas d'accès au constructeur privé dans la base). Les modèles ne font même pas partie du problème. vous pouvez recréer le problème sans eux. On dirait que c'est un problème de MI, que VS a toujours été un peu lent à faire les choses correctement.
J'ai changé les étiquettes pour refléter cette découverte.
Publié au dépôt de bug de MS
J'ai inclus un travail autour dans le code exemple.
Je suis assez sûr que * template * ne peut pas être un constructeur de copie. Mais * template class * peut avoir un constructeur de copie défini. En ce qui concerne votre exemple, un code comme celui-ci devait déclencher une récursion infinie dans le constructeur de copie, mais je suppose que dans les cas simplifiés, le compilateur a optimisé les choses. – SigTerm
Votre exemple est-il le bon? Je veux dire qu'il semble que 'T1' est' base' et 'T2' est' another_base' mais vous passez l'entier à 'T1' (qui a le constructeur du template) et' x' à 'T2' (qui a le' int' constructeur). – Troubadour
Quel compilateur utilisez-vous? – SCFrench