On 20-Feb-2010, Bruno Haible wrote: | And when I change the first line to | | namespace system { | #include <fcntl.h> | } | using namespace system; | | then there is a different error message: | | $ g++ -S foo.cc | foo.cc: In function ‘int bar_uses_gnulib_implicitly()’: | foo.cc:37: error: reference to ‘open’ is ambiguous | foo.cc:12: error: candidates are: int (* const gnulib::open)(const char*, int, ...) | /usr/include/fcntl.h:85: error: int system::open(const char*, int, ...) | foo.cc:37: error: reference to ‘open’ is ambiguous | foo.cc:12: error: candidates are: int (* const gnulib::open)(const char*, int, ...) | /usr/include/fcntl.h:85: error: int system::open(const char*, int, ...) | | Do you see a way to make it work?
Yesterday I was using a simplified example that I thought captured all the necessary details, but I missed the original extern declaration of the system function. But how about the following example? Does it have all the required features? It seems to work for me, but maybe I'm again missing something. It compiles and runs as I would expect with with GCC 3.3, 4.0, 4.1, 4.2, 4.3, and 4.4 with all the combinations of GNULIB_OPEN and REPLACE_OPEN. I renamed your "system" namespace to "gnulib_system_namespace" because older versions of GCC (3.3 through 4.2) failed with bar.cc:3: error: 'namespace system { }' redeclared as different kind of symbol /usr/include/stdlib.h:666: error: previous declaration of 'int system(const char*)' bar.cc:38: error: 'system' is not a class or namespace so I think the namespace that wraps the C/POSIX functions should probably use a name that won't conflict. jwe
#include <iostream> namespace gnulib_system_namespace { #include <fcntl.h> } extern "C" { extern int rpl_open (const char *filename, int flags, ...) __attribute__ ((__nonnull__ (1))); } #define GNULIB_OPEN 1 #define REPLACE_OPEN 1 class foo { public: foo (void) { } void open (void) const; }; #if GNULIB_OPEN # if REPLACE_OPEN # ifndef __cplusplus # undef open # define open rpl_open # endif # endif #endif #ifdef __cplusplus namespace gnulib { int (*const open) (const char *filename, int flags, ...) = # if GNULIB_OPEN # if REPLACE_OPEN ::rpl_open; # else gnulib_system_namespace::open; # endif # else gnulib_system_namespace::open; # endif } using gnulib::open; #endif int rpl_open (const char *filename, int flags, ...) { std::cerr << "foo-i-hithere" << std::endl; return 42; } void foo::open (void) const { std::cerr << "foo::open" << std::endl; } int main (void) { int status = open ("/dev/null", O_RDWR); std::cerr << status << std::endl; foo x; x.open (); return 0; }