home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   comp.lang.c++.moderated      Moderated discussion of C++ superhackery      33,346 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 31,858 of 33,346   
   =?ISO-8859-1?Q?Daniel_Kr=FCgler?= to All   
   Re: When is the non-local static variabl   
   26 Jan 12 23:46:27   
   
   be4c6be8   
   From: daniel.kruegler@googlemail.com   
      
   Am 26.01.2012 20:49, schrieb paul_71:   
   [..]   
   > Yes, this is a commonly used idiom of "registrars" for e.g.   
   > deserialization object factories... Unfortunately it is very easy to   
   > break on every implementation I have tried. If such non-locals as the   
   > "sc" from your example live in "static libraries" then the applied   
   > linker optimization strategies are not able to see the side effects of   
   > "sc" constructors. In your example, whenever a linker sees a usage of   
   > "sc" (as in sc.SomeFunction()) the constructor for sc will be run. If   
   > it does not, the symbol "sc" is just removed and the program behaves   
   > as it would not be present.   
      
   As explained in my reply, this is easy to fix for static libraries in   
   practice. Just define a static variable in every *header* of the library   
   where the constructor calls a single time a function local static   
   variable. Here a sketch:   
      
   // register_api.h: (Needed for registration)   
      
   namespace api {   
      
   template   
   class RegistryProxy;   
      
   namespace details {   
      
   class Registry   
   {   
     template   
     friend class api::RegistryProxy;   
      
     Registry(const char* id);   
   };   
      
   } // details   
      
   template   
   class RegistryProxy   
   {   
     static details::Registry& init(const char* id) {   
       static details::Registry result(id);   
       return result;   
     }   
   public:   
     RegistryProxy(const char* id) { init(id); }   
   };   
      
   }   
      
   // query_api.h: (needed to check the registry contents)   
      
   #include    
   #include    
      
   namespace api {   
      
   typedef std::vector ContType;   
      
   ContType allIds();   
      
   }   
      
   // register_lib.cpp   
   #include "register_api.h"   
   #include "query_api.h"   
      
   namespace api {   
      
   namespace details {   
   namespace {   
      
   inline ContType& ids()   
   {   
     static ContType result;   
     return result;   
   }   
      
   } // anon   
      
   Registry::Registry(const char* id)   
   {   
     ids().push_back(id);   
   }   
      
   } // details   
      
   ContType allIds()   
   {   
     return details::ids();   
   }   
      
   } // api   
      
   Now lets consider a static library user_api, which provides an api header:   
      
   //user_api.h:   
      
   #include "user_api_register.h"   
      
   namespace user_api {   
      
   // Something to export   
      
   }   
      
   // user_api_register.h (internally needed to ensure proper registration)   
   #include "register_api.h"   
      
   namespace user_api {   
   namespace details {   
      
   class UserType;   
      
   namespace {   
     api::RegistryProxy force_registration_do_not_use("user_api");   
   }   
      
   }   
   }   
      
   Finally we have a test program that depends on the static user library   
   and does show the registry contents:   
      
   #include    
   #include    
   #include    
   #include "query_api.h"   
      
   #include "user_api.h" // This could have been included by any other   
                         // TU of the main program. For simplicity it   
                         // is included here.   
      
   int main()   
   {   
     api::ContType ids = api::allIds();   
     std::copy(ids.begin(), ids.end(),   
   std::ostream_iterator(std::cout, "\n"));   
   }   
      
   Greetings from Bremen,   
      
   Daniel Krügler   
      
      
   --   
         [ See http://www.gotw.ca/resources/clcm.htm for info about ]   
         [ comp.lang.c++.moderated.    First time posters: Do this! ]   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca