Time extension constant

I have a question about some standard C ++ matching or lack thereof.

In my project, I use some kind of simple Guard class that uses the const trick. I use Visual Studio 2005 and there are two configurations: one for normal release builds, the second for unit tests.

In both cases, at the end there is some temporary freezing of the const reference, but what happens at this time is a problem. For the release configuration, the const reference refers directly to temp created when the helper function template is returned that creates the Guard instance (no copy constructor is called, not even created for this).

But for unit test conf, the template of the function template is first copied, and then its destructor is called, doing what should be done only after the reference to const stops working.

I solved the problem by disabling the original defender in the constructor of the copy of the base class (therefore, the action in the destructor does not start for the configuration for which the copy constructor is called), but it bothers me:

Is copy-time compatibility standard? Does the standard indicate that the const reference should point directly to temp, or is this implementation-defined behavior not specified in the standard?

I based my code roughly on the Scope Guard article in the DDJ and Herb Sutter gotw 88 article, but both of these sources do not seem to take into account an earlier call to the destructor.

Any information from someone more knowledgeable would be appreciated.

EDIT:

, :

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;
+3
1

. :

T foo()
{
  return T();
}

int main()
{
  const T& x = foo();
}

, , foo . foo. main ( ) x.
, foo, , , .

, ++ . foo .
, , .

++ 6.6.3 ([stmt.return]) 12.2 ([class.temporary]).

+4

Source: https://habr.com/ru/post/1772830/


All Articles