J'ai une question sur la conformité à la norme C++ ou son absence.Référence constante pour l'allongement temporaire de la durée de vie
Dans mon projet, j'utilise une classe Guard simple qui utilise l'astuce de référence const. J'utilise Visual Studio 2005 et il existe deux configurations: une pour la version normale et la seconde pour les tests unitaires.
Dans les deux cas, il y a une suspension temporaire sur la référence const à la fin, mais ce qui se passe entre-temps, c'est le problème. Pour la configuration de version, la référence const pointe directement sur la température créée dans le retour du modèle de fonction d'assistance qui crée l'instance de Guard (aucun constructeur de copie n'est appelé, même pas instancié d'ailleurs).
Mais pour le test d'unité conf, le modèle de fonction temp est d'abord copié, puis son destructeur est appelé, en faisant ce qui doit être fait seulement après que la référence const est hors de portée.
J'ai résolu le problème en désactivant la garde d'origine dans le constructeur de copie de classe de base (donc l'action destructor ne se déclenche pas pour config pour laquelle constructeur de copie est appelé), mais ce qui me dérange est:
Est-ce le Comportement de copie-le-temporaire conforme aux normes? La norme indique-t-elle que la référence const doit pointer directement sur la température, ou ce comportement défini par l'implémentation n'est-il pas spécifié dans la norme?
J'ai basé mon code en gros sur l'article de Scope Guard dans DDJ et l'article de Herb Sutter sur gotw 88, mais ces deux sources ne semblent pas tenir compte de l'appel du destructeur précédent.
Toute information de quelqu'un de mieux informé sera appréciée.
EDIT:
Ok le code est quelque chose comme ceci:
class GuardBase
{
public:
GuardBase() : m_enabled(true)
{}
//this is done because in normal build no copy constructor is called (directly using the function temporary)
//but for UT conf somehow the original temp is copied and destroyed
GuardBase(const GuardBase& other)
{
other.disable();
}
void disable() const
{
m_enabled = false;
}
protected:
//member is mutable because we will access the object through the const reference
mutable bool m_enabled;
};
template< typename Arg, typename ObjType, typename MemberMethod >
class Guard1Arg : public GuardBase
{
public:
Guard1Arg(ObjType& obj, MemberMethod remover, Arg arg) : m_arg(arg), m_remover(remover), m_object(obj)
{}
~Guard1Arg()
{
if (m_enabled)
{
(m_object.*m_remover)(m_arg);
}
}
private:
Arg m_arg;
MemberMethod m_remover;
ObjType& m_object;
//this class should not be assigned
Guard1Arg& operator=(const Guard1Arg& other);
};
//utility template function used to create Guards using member functions with 1 argument
template<typename MemberFunction, typename Obj, typename Arg>
Guard1Arg<Arg, Obj, MemberFunction> MakeGuard1Arg(Obj& obj, MemberFunction memberFunction, Arg& arg)
{
return Guard1Arg<Arg, Obj, MemberFunction>(obj, memberFunction, arg);
}
#define GUARD_CREATE(arg, remover) const GuardBase& guard = MakeGuard1Arg(*this, remover, arg);
#define GUARD_DISABLE guard.disable();
#define GUARD_FRIEND template< typename Arg, typename ObjType, typename MemberMethod > friend class Guard1Arg;
Vous avez un code pour illustrer cela? – sharptooth
Sans le code, il n'est pas possible de dire exactement. Toutes les réponses seront des suppositions. –