Thread: Instantiate FILE handler in header file

  1. #16
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    I need to define a macro in a header file in C++ which is called lots of time in the application (for particular, thus non-negociable, log reasons).
    O_o

    The C++ language doesn't guarantee order of initialization of global objects.

    The C++ language only guarantees order of destruction regarding `std::atexit` with respect to construction of global or `static` objects not the use of any such objects.

    The C++ language has no concept of a "phoenix" lifetimes so a destroyed global or `static` object must not be used which complicates any usage by any other global or `static` objects.

    The easiest way to resolve all of the related problems is with an interface which pretends that opening, writing, and then closing a file is a single atomic operation.

    I have quickly read that this is possible by defining a class in the header, with diffferent possibilities for the instantiation.
    I have no issues with using a macro for logging if you allow builds without any logging, but I'd argue that you should still be using a named `inline` function within the definition of such a macro.

    I considered that for my example, but then there would be (potentially) one copy for every translation unit that included the header. Still an improvement over opening and closing on every call though.
    You could solve that particular issue with a normal `inline` function yielding a reference or pointer to a constructed `std:fstream` object.

    Soma

    Code:
    #include <cstdlib>
    #include <iostream>
    #include <string>
    
    #if !defined(__PRETTY_FUNCTION__)
    #    define __PRETTY_FUNCTION__ __PRETTY_FUNCTION__
    #endif //?! (__PRETTY_FUNCTION__)
    
    struct SExample
    {
         SExample():
              m(1)
         {
              std::cout << __PRETTY_FUNCTION__ << ": " << m << "\n";
         };
         ~SExample()
         {
              std::cout << __PRETTY_FUNCTION__ << ": " << m << "\n";
              --m;
         };
         void doSomething()
         {
              std::cout << __PRETTY_FUNCTION__ << ": " << m << "\n";
         }
         int m;
    };
    
    void DoSomething1
    (
         const char * f
    )
    {
         static SExample s;
         std::cout << __PRETTY_FUNCTION__ << ": " << f << "\n";
         s.doSomething();
    }
    
    void DoSomething2()
    {
         std::cout << __PRETTY_FUNCTION__ << "\n";
         DoSomething1("use static `s` in the `DoSomething2` function");
    }
    
    int main
    (
         int argc
       , char ** argv
    )
    {
         if((argc > 1) && (std::string("misordered") == argv[1]))
         {
              // register a function *before* `s` is constructed
              std::atexit(DoSomething2);
              DoSomething1("use static `s` in the `main` function");
         }
         else
         {
              DoSomething1("use static `s` in the `main` function");
              // register a function *after* `s` is constructed
              std::atexit(DoSomething2);
         }
         return(0);
    }
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  2. #17
    Registered User
    Join Date
    Oct 2008
    Posts
    77
    Thanks everybody for the time spent on this issue. I have tried the template and inline options, it builds ok but error in link. The phantomotap explanation is rigurous, the solution is heeeeeeavy for the little I need. I go back to the macro as I've defined it just does the job.
    Many thanks again (a little bit frustrated because my first googles gave me a glimps with another possible outcome!

  3. #18
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    // In a .cpp file
    std::ostream MyLogFile("MyLogFile.log");

    // In a header
    extern std::ostream MyLogFile;

    // Wherever you want to log. Be sure to include the header.
    MyLogFile << whatever;

    Pretty much the equivalent of your macro, but with the disadvantage of having globals (non-deterministic construction/destruction).
    Last edited by Elysia; 07-08-2016 at 06:20 AM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #19
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    I have tried the template and inline options, it builds ok but error in link.
    O_o

    If you posted the sample code and the linker error, you most likely would have received some help.

    The phantomotap explanation is rigurous, the solution is heeeeeeavy for the little I need.
    ^_^;

    A rigorous post from me would include which version of the standard fixed part of the issue and hacks to account for issues with compilers which predate the relevant standard.

    Soma
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 09-12-2014, 04:45 PM
  2. Replies: 16
    Last Post: 04-05-2014, 09:23 PM
  3. Replies: 11
    Last Post: 09-25-2011, 12:22 AM
  4. Replies: 30
    Last Post: 06-19-2006, 12:35 AM
  5. Replies: 4
    Last Post: 12-14-2005, 02:21 PM

Tags for this Thread