1. 8
  1.  

  2. 1

    GNU, clang, and Visual C++ also support __COUNTER__ which I recommend over __LINE__ since people might use defer in a macro.

    I’m divided as to whether I prefer parenthesis or braces. The macro they suggested does save a character ; but I think this looks better:

    #define DEFER ScopeGuard CONCAT(__defer__, __LINE__) = [&] ( )
    DEFER { file.close(); }
    

    (but how often is this really required in C++? Surely files know how to close themselves…)

    1. 1

      std::function produces extremely bad code, like pages of assembly for something trivial, and should not be used.

      You can do it like this instead:

      #define CONCAT_HELPER( a, b ) a##b
      #define CONCAT( a, b ) CONCAT_HELPER( a, b )
      #define COUNTER_NAME( x ) CONCAT( x, __COUNTER__ )
      
      template< typename F >
      struct ScopeExit {
              ScopeExit( F f_ ) : f( f_ ) { }
              ~ScopeExit() { f(); }
              F f;
      };
      
      template< typename F >
      inline ScopeExit< F > MakeScopeExit( F f ) {
              return ScopeExit< F >( f );
      };
      #define SCOPE_EXIT( code ) auto COUNTER_NAME( SCOPE_EXIT_ ) = MakeScopeExit( [&]() { code; } )
      

      (from http://the-witness.net/news/2012/11/scopeexit-in-c11/)

      1. [Comment from banned user removed]

        1. 2

          No, not really – this is for when any particular scope exits; atexit can only fire when the whole process is being shutdown.

          1. [Comment from banned user removed]

            1. 1

              Except in go you can easily make a closure to make a new scope.

              func () { v = a() defer v.Close() … } ()

              1. 1

                Except in go you can easily make a closure to make a new scope.

                Do you not understand that closures are a type of function and your observation changes nothing in the fact that Go’s “defer” works at function scope, as described in official docs?

                https://tour.golang.org/flowcontrol/12