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,828 of 33,346   
   Jonathan Thornburg to All   
   boost::format vs. in-class 'static const   
   22 Jan 12 00:50:22   
   
   From: clcppm-poster@this.is.invalid   
      
   I recently ran across an interesting problem in combining two parts of   
   C++ that individually work beautifully:  boost::format  and in-class   
   'static const int' constants.   
      
   The following toy code illustrates the problem:   
      
      #include    
      #include "boost/format.hpp"   
      
      using std::cout;   
      using boost::format;   
      
      // identity function   
      inline int I(int x) { return x; }   
      
      // declaration of class containing in-class 'static const int'   
      class   foo   
              {   
      public:   
              static const int N = 42;   
              };   
      
      int main()   
      {   
      cout << "raw output:   N  = " <<   foo::N << "\n";   
      cout << "raw output: I(N) = " << I(foo::N) << "\n";   
      #if 0   
      cout << format("boost::format output:   N  = %d\n") %   foo::N;   
      #endif   
      cout << format("boost::format output: I(N) = %d\n") % I(foo::N);   
      
      return 0;   
      }   
      
   Here we've declared a class  foo  containing an in-class constant int   
    foo::N .  So long as we don't try to take the address of  foo::N   
   (i.e., so long as we don't try to form a pointer or reference to it)   
   everything is fine, and in particular we don't need to explicitly   
   define  foo::N  outside the class declaration.   
      
   In particular, there's no problem in printing  foo::N  by sending it to   
    std::cout , or in passing  foo::N  by value to a function  I() .  And   
   there's no problem in using  boost::format  to print  I(foo::N) .   
   However, if we change the "#if 0" to "#if 1", and thus try to print   
    foo::N  using  boost::format , then the program fails to link   
         [I'm using g++ 4.2.4 on an OpenBSD 5.0 system, with   
   	boost 1.42.0p7, but I think this behavior is generic   
   	and should be the same for any reasonable C++ system   
   	and boost version.]   
   because  boost::format  takes its arguments by reference-to-const, so   
   we're now asking the compiler to form a reference to  foo::N , which   
   has never been explicity defined.   
      
         [In the actual application code where I encountered this   
   	problem, there were a lot of templates around, and I at   
   	first thought this was template instantiation (or more   
   	accurately, non-instantiation) problem.]   
      
      
      
   So, what to do if we want to use boost::format to print out (messages   
   which include) in-class constant ints?  I can see several possible   
   solutions:   
      
   We could explicitly define the in-class constant ints outside the class   
   declaration.  This is awkward on two grounds:   
   * it makes the code less readable: N must then be initialized in the   
     definition, which lives in a .cc file far away (in the source code)   
     from the .hh file where the class is declared, so reading the .hh file   
     no longer tells the programmer a key piece of information about N   
     (its value).   
   * if the class is actually a template, the definition needs to be   
     replicated for each instantiation of the template   
      
   We could use an enum instead of 'static const int', so as to get a truly   
   compile-time constant.  Alas, boost::format  (at least in the version I'm   
   using) doesn't know how to output an enum, so code trying to do so fails   
   to compile:   
   > boost-format-call-by-ref2.cc:26: error: no match for 'operator%' in   
   'boost::basic_format, std::allocator   
   >(((const char*)"boost::format output:   M  = %d\012")) % M'   
      
   We could use an explicit identity function  I()  which takes its argument   
   by *value*, and (as in the above code) apply  I()  to the in-class constant   
   int before printing.   
      
      
      
   At the moment my preferred solution is the last of these, with an explicit   
   identity function.  Are there other (more-elegant) solutions?  Are there   
   other cogent arguments for/against various solutions?   
      
   --   
   -- "Jonathan Thornburg [remove -animal to reply]"    
      Dept of Astronomy & IUCSS, Indiana University, Bloomington, Indiana, USA   
      "Washing one's hands of the conflict between the powerful and the   
       powerless means to side with the powerful, not to be neutral."   
                                         -- quote by Freire / poster by Oxfam   
      
      
         [ 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