From: ab4ag1@hotmail.com   
      
   (Note: Only the introduction is linux specific.)   
   On Linux there are two functions called strerror_r. One can choose   
   between those function using appropriate preprocessor flags. The problem   
   is that the functions have different return types which is why I tried   
   to wrap the handling code in another C++ function. I wanted to hide the   
   distinction using templates.   
      
   The idea is to create template specializations for each implementation   
   and let the compiler decide which one to pick. For some reason g++ 4.5.3   
   always seems to instantiate both methods and I don't know why.   
      
   Here is what I think should happen:   
   1. The compiler evaluates Equals in line 83   
   2. The compiler instantiates Call (on *my* system is true).   
   Call is not instantiated.   
   3. The compiler instantiates Strerror_r because of 2.). Also   
   because of 2.), Strerror_r is never instantiated.   
   4. The compiler sees fitting returns types in line 19, the mismatch in   
   line 36 is ignored.   
      
   Where is my mistake?   
      
   Compiler: g++ 4.5.3   
      
   Error Message:   
   map.cpp: In member function ‘int Strerror_r::posix(int, char*, size_t)’:   
   map.cpp:36:40: error: invalid conversion from ‘char*’ to ‘int’   
      
   (On my system the GNU's strerror_r version is used (char* return type))   
      
      
   Code:   
   #include    
   #include    
   #include // strerror_r   
      
      
   typedef char* (*Gnu_strerror_r_type)(int, char*, size_t);   
   typedef int (*Posix_strerror_r_type)(int, char*, size_t);   
      
      
   template   
   struct Strerror_r;   
      
      
   template<>   
   struct Strerror_r   
   {   
    int gnu(int error, char* buffer, size_t size)   
    {   
    char* p( strerror_r(error, buffer, size) ); // line 19   
    if( !p || p == buffer )   
    return 0;   
      
    strncpy(buffer, p, size-1);   
    buffer[size-1] = 0;   
    return 0;   
    }   
   };   
      
      
      
   template<>   
   struct Strerror_r   
   {   
    // Why is this instantiated???   
    int posix(int error, char* buffer, size_t size)   
    {   
    return strerror_r(error, buffer, size); // Line 36 here   
    }   
   };   
      
      
      
   template   
   struct Call;   
      
      
   template<>   
   struct Call   
   {   
    Strerror_r s;   
    int execute(int e, char* p, size_t sz) { return s.gnu(e,p,sz); }   
   };   
      
      
      
   template<>   
   struct Call   
   {   
    Strerror_r s;   
    int execute(int e, char* p, size_t sz) { return s.posix(e,p,sz); }   
   };   
      
      
      
   template   
   struct Equals   
   {   
    static const bool value = false;   
   };   
      
      
   template   
   struct Equals   
   {   
    static const bool value = true;   
   };   
      
      
      
   template   
   int my_strerror_r_impl(   
    T, int error, char* buffer, size_t size)   
   {   
    Call::value> c; // line 83   
    return c.execute(error, buffer, size);   
   }   
      
      
      
   int my_strerror_r(int error, char* buffer, size_t size)   
   {   
    return my_strerror_r_impl(&strerror_r, error, buffer, size);   
   }   
      
      
      
   int main()   
   {   
    char buffer[1024];   
    memset(buffer, 0, sizeof(buffer));   
    if( my_strerror_r(ENOSYS, buffer, sizeof(buffer)) < 0 )   
    return 1;   
      
    std::printf( "Message: '%s'\n", buffer );   
   }   
      
      
       
      
      
   --   
    [ 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)   
|