Je me suis heurté aujourd'hui à un problème assez subtil sur lequel j'aimerais avoir votre avis.
Considérons la classe d'idiomes à corps partagé suivante :
struct S
{
S() : p_impl(new impl) {}
private:
struct impl;
boost::shared_ptr<impl> p_impl;
};
Le plaisir apparaît lorsque vous essayez de les transformer en vecteurs de la manière suivante :
std::vector<S> v(42);
Désormais, avec MSVC 8 au moins, tous les éléments de la section v
partagent le même impl
membre. En fait, ce qui cause ce problème est le vector
constructeur :
template <typename T, typename A = ...>
class vector
{
vector(size_t n, const T& x = T(), const A& a = A());
...
};
Dans les coulisses, un seul S
est construit par défaut, l'objet n
éléments de la vector
sont copiés à partir de celui-ci.
Maintenant, avec C++11, il y a des références rvalue. Donc ça ne peut pas fonctionner comme ça. Si une vector
est construit comme suit
std::vector<S> v(42);
alors il est fort probable que les implémentations choisiront de construire par défaut l'option n
à l'intérieur du vecteur, puisque la construction par copie peut ne pas être disponible. Il s'agirait d'un changement de rupture dans ce cas.
Ma question est la suivante :
- La norme C++03 impose-t-elle que
std::vector
doit avoir un constructeur défini comme ci-dessus, c'est-à-dire avec un argument par défaut ? En particulier, y a-t-il une garantie que les entrées de l'objet vectoriel seront copiées au lieu d'être construites par défaut ? - Que dit la norme C++11 sur ce même point ?
- Je vois là la possibilité d'un changement de rupture entre C++03 et C+11. Ce problème a-t-il été étudié ? Résolu ?
PS : S'il vous plaît pas de commentaires sur le constructeur par défaut de la classe S
ci-dessus. C'était ça ou la mise en œuvre d'une forme de construction paresseuse.