Hi John,

Ralf proposes:
> I suggest you could
> produce a helper header to #undef them again; you could even do that
> automatically during bootstrap with above.  Then only a portability
> layer would need to avoid using these symbols in another namespace.

This would only be a makeshift. Your example

>   class foo
>   {
>   public:
>     ...
>     int open (some, args);
>     ...
>   };

>   int foo::open (some, args) { ... }

clearly indicates that in C++, one should minimize the use of
preprocessor defines for lowercase identifiers.

C++ has its own, idiosyncratic, ways of aliasing and overriding
functions. If we were to change gnulib's fcntl.h like this:

*** lib/fcntl.in.h.orig Thu Feb 18 23:44:21 2010
--- lib/fcntl.in.h      Thu Feb 18 23:31:02 2010
***************
*** 79,87 ****
  
  #if @GNULIB_OPEN@
  # if @REPLACE_OPEN@
! #  undef open
! #  define open rpl_open
! extern int open (const char *filename, int flags, ...) _GL_ARG_NONNULL ((1));
  # endif
  #elif defined GNULIB_POSIXCHECK
  # undef open
--- 79,89 ----
  
  #if @GNULIB_OPEN@
  # if @REPLACE_OPEN@
! #  ifndef __cplusplus
! #   undef open
! #   define open rpl_open
! #  endif
! extern int rpl_open (const char *filename, int flags, ...) _GL_ARG_NONNULL 
((1));
  # endif
  #elif defined GNULIB_POSIXCHECK
  # undef open
***************
*** 111,116 ****
--- 113,132 ----
  }
  #endif
  
+ #ifdef __cplusplus
+ namespace gnulib
+ {
+ # if @GNULIB_OPEN@
+   int (*const open) (const char *filename, int flags, ...) =
+ #  if @REPLACE_OPEN@
+     rpl_open;
+ #  else
+     open;
+ #  endif
+ # endif
+ }
+ #endif
+ 
  /* Fix up the FD_* macros, only known to be missing on mingw.  */
  
  #ifndef FD_CLOEXEC


Then you can use the identifier 'gnulib::open' on any platform.
On platforms where REPLACE_OPEN = 1, calls to 'gnulib::open'
will be automatically inlined to calls to 'rpl_open', on the
other platforms to calls to the C function 'open'.

Here are some code that compiles fine with this modified gnulib fcntl.h:

  // A class 'foo' can have a member 'open' without any problem.
  class foo {
    int open (const char *arg);
  };

  // This function invokes the global C function 'open'.
  int bar_uses_global () {
    return open ("/dev/null", O_RDWR);
  }

  // Does not work, leads to
  //   error: reference to ‘open’ is ambiguous
  //   /usr/include/fcntl.h:85: error: candidates are: int open(const char*, 
int, ...)
  //   foo.cc:9: error:                 int (* const gnulib::open)(const char*, 
int, ...)
  //using namespace gnulib;

  // This function invokes the global C function 'rpl_open' or 'open', 
depending on platform.
  int bar_uses_gnulib () {
    return gnulib::open ("/dev/null", O_RDWR);
  }


Additionally, there is some talk about a future standard namespace called 
'posix'. [1][2]
You can already forward-adapt your code by using posix:: in place of gnulib::

  // Compatibility with future C++1X:

  namespace posix = gnulib;

  int bar_uses_gnulib_via_posix () {
    return posix::open ("/dev/null", O_RDWR);
  }


Bruno


[1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2667.htm
[2] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2733.html


Reply via email to