By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,331 Members | 1,359 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,331 IT Pros & Developers. It's quick & easy.

overloading std C functions with a namespace

P: n/a
I am working with a large C++ program which, for reasons of backward
compatibility, uses C's printf and fprintf rather than iostreams.

For a certain type of build I want to provide new functions that
change the behaviour of printf and fprintf, and I planned to make them
available using a convenient namespace, called 'herring', say, like this:

using herring::printf;
using herring::fprintf;

Now, all the other classes and functions etc are in their own
namespace, called 'haddock' say. So all the code has the lines

namespace haddock{
...
}

around it. It would be most convenient to put the 'using' directives
just inside the 'namespace', like this:

#include <stdio.h>

namespace herring{
int printf(const char*, ...);
int fprintf(FILE*, const char*, ...);
}

namespace haddock{
using herring::fprintf;
using herring::printf;

void halibut(){

FILE *fp;
fprintf(fp, "hoho");
printf("haha");
}

}

But this does not work: g++ -c gives me

name.C: In function `void haddock::halibut()':
name.C:15: call of overloaded `fprintf(FILE*&, const char[5])' is
ambiguous
name.C:5: candidates are: int herring::fprintf(FILE*, const char*, ...)
/usr/local/lib/gcc-lib/i686-pc-linux-gnu/3.2.1/include/stdio.h:307:
int fprintf(FILE*, const char*, ...)

on a bog-standard RH Linux box with g++ 3.2.1

However, this does work:

#include <stdio.h>

namespace herring{
int printf(const char*, ...);
int fprintf(FILE*, const char*, ...);
}

namespace haddock{
using herring::printf;

void halibut(){
using herring::fprintf;

FILE *fp;
fprintf(fp, "hoho");
printf("haha");
}

}

which is fine, but would mean I have to put the 'using' into every
function, rather than simply changing
namespace haddock{
to
namespace haddock{ using herring::fprintf; using herring::printf;
(which I can actually do in a single header file).

Anyway, my question is, why does the second code compile but not the
first?

Thanks.
Jul 22 '05 #1
Share this Question
Share on Google+
7 Replies


P: n/a
<zb*****@amtp.liv.ac.uk> wrote...
I am working with a large C++ program which, for reasons of backward
compatibility, uses C's printf and fprintf rather than iostreams.

For a certain type of build I want to provide new functions that
change the behaviour of printf and fprintf, and I planned to make them
available using a convenient namespace, called 'herring', say, like this:

using herring::printf;
using herring::fprintf;

Now, all the other classes and functions etc are in their own
namespace, called 'haddock' say. So all the code has the lines

namespace haddock{
...
}

around it. It would be most convenient to put the 'using' directives
just inside the 'namespace', like this:

#include <stdio.h>

namespace herring{
int printf(const char*, ...);
int fprintf(FILE*, const char*, ...);
}

namespace haddock{
using herring::fprintf;
using herring::printf;

void halibut(){

FILE *fp;
fprintf(fp, "hoho");
printf("haha");
}

}

But this does not work: g++ -c gives me

name.C: In function `void haddock::halibut()':
name.C:15: call of overloaded `fprintf(FILE*&, const char[5])' is
ambiguous
name.C:5: candidates are: int herring::fprintf(FILE*, const char*, ...)
/usr/local/lib/gcc-lib/i686-pc-linux-gnu/3.2.1/include/stdio.h:307:
int fprintf(FILE*, const char*, ...)

on a bog-standard RH Linux box with g++ 3.2.1

However, this does work:

#include <stdio.h>

namespace herring{
int printf(const char*, ...);
int fprintf(FILE*, const char*, ...);
}

namespace haddock{
using herring::printf;

void halibut(){
using herring::fprintf;

FILE *fp;
fprintf(fp, "hoho");
printf("haha");
}

}

which is fine, but would mean I have to put the 'using' into every
function, rather than simply changing
namespace haddock{
to
namespace haddock{ using herring::fprintf; using herring::printf;
(which I can actually do in a single header file).

Anyway, my question is, why does the second code compile but not the
first?


In the second case the 'using' directive inside 'void halibut()'
function _hides_ the declaration of any other 'fprintf', whereas
at a namespace 'haddock' scope no hiding is occurring.

I wrote this, and it seems logical to me, although I didn't confirm
with the Standard. Let the gurus correct me if I am wrong.

Victor
Jul 22 '05 #2

P: n/a
"Victor Bazarov" <v.********@comAcast.net> wrote in message news:<eNcqc.16605$qA.2058485@attbi_s51>...
[redacted]


Now, I'm not the language guru that Victor is, and probably never will
be, but if the OP had used

#include <cstdio>

instead of

#include <stdio.h>

Wouldn't printf/fprintf be in the std namespace, so that there would
be no ambiguity between (the imported) herring::printf and
std::printf, while with the latter (as posted case), we have the
ambiguity between (the imported) herring::printf and ::printf
Jul 22 '05 #3

P: n/a
red floyd wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message news:<eNcqc.16605$qA.2058485@attbi_s51>...
[redacted]

Now, I'm not the language guru that Victor is, and probably never will
be, but if the OP had used

#include <cstdio>

instead of

#include <stdio.h>

Wouldn't printf/fprintf be in the std namespace, so that there would
be no ambiguity between (the imported) herring::printf and
std::printf, while with the latter (as posted case), we have the
ambiguity between (the imported) herring::printf and ::printf


You're correct. However, the OP stated that it's a legacy code, so it is
quite possible that he didn't want to change the includes. Besides, the
question was "why it's so", not "how to fix it". Aside from that, you're
absolutely right.

Victor
Jul 22 '05 #4

P: n/a
zb*****@amtp.liv.ac.uk wrote in message news:<c8**********@news.liv.ac.uk>...
I am working with a large C++ program which, for reasons of backward
compatibility, uses C's printf and fprintf rather than iostreams.

For a certain type of build I want to provide new functions that
change the behaviour of printf and fprintf, and I planned to make them
available using a convenient namespace, called 'herring', say, like this:

using herring::printf;
using herring::fprintf;


I'd handle this a little bit differently. I'd start by including
<cstdio> instead of stdio.h. This has versions of printf and fprintf
that live in the std namespace. So, by including both headers, we
have an std::printf and a herring::printf.

Then comes the trickery: we add a namespace alias:

namespace desired = herring;

Then our using declarations become:

using desired::fprintf;
using desired::printf;
using desired::puts;
using desired:: ...

and switching from one to the other only involves changing the alias
-- to switch back to using the standard functions, we just edit it to:

namespace desired = std;

and compiler deals with the rest automagically.
--
Later,
Jerry.

The universe is a figment of its own imagination.
Jul 22 '05 #5

P: n/a
On Tue, 18 May 2004 09:20:55 -0400, Victor Bazarov
<v.********@comAcast.net> wrote:
red floyd wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message news:<eNcqc.16605$qA.2058485@attbi_s51>...
[redacted]

Now, I'm not the language guru that Victor is, and probably never will
be, but if the OP had used

#include <cstdio>

instead of

#include <stdio.h>

Wouldn't printf/fprintf be in the std namespace, so that there would
be no ambiguity between (the imported) herring::printf and
std::printf, while with the latter (as posted case), we have the
ambiguity between (the imported) herring::printf and ::printf


You're correct. However, the OP stated that it's a legacy code, so it is
quite possible that he didn't want to change the includes. Besides, the
question was "why it's so", not "how to fix it". Aside from that, you're
absolutely right.


Not to mention that very few compilers have conforming <cheader>
headers - mostly they just pull the global declarations into the
standard namespace with using declarations. e.g.

//common but non-conforming <cstdio>
#include <stdio.h>
namespace std
{
using ::printf;
using ::fprintf;
//etc.
}

Which is unhelpful for the OP.

Tom
--
C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Jul 22 '05 #6

P: n/a
Thanks for your interest and interesting comments...
red floyd wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message news:<eNcqc.16605$qA.2058485@attbi_s51>...
[redacted]
Now, I'm not the language guru that Victor is, and probably never will
be, but if the OP had used

#include <cstdio>

instead of

#include <stdio.h>

Wouldn't printf/fprintf be in the std namespace, so that there would
be no ambiguity between (the imported) herring::printf and
std::printf, while with the latter (as posted case), we have the
ambiguity between (the imported) herring::printf and ::printf

The thing that puzzles me is that, in the code I posted, the compiler
sees _no_ ambiguity between the printf's (and I've verified that
herring::printf is actually called) but it does for the
fprintf's. This looks like an anomaly to me.

Victor seems to suggest that putting the 'using' directive inside the
'namespace haddock{...}' scope should not hide the previous
declaration - as it does with printf, whereas putting it inside the
function should - as it does for both printf and fprintf. If this is
the case then it is the printf behaviour which anomalous.
You're correct. However, the OP stated that it's a legacy code, so it is
quite possible that he didn't want to change the includes. Besides, the
question was "why it's so", not "how to fix it". Aside from that, you're
absolutely right.


Not to mention that very few compilers have conforming <cheader>
headers - mostly they just pull the global declarations into the
standard namespace with using declarations. e.g.

//common but non-conforming <cstdio>
#include <stdio.h>
namespace std
{
using ::printf;
using ::fprintf;
//etc.
}


This is indeed what my version here does. Changing the header to
<cstdio> doesn't fix the problem in my toy code, although the argument
sounds sensible to me. In any case, as suggested, in the real code
there's no way I can easily go and change it everywhere, and I am sort
of resigned to not being able to get what I wanted.

Thanks again.

Jul 22 '05 #7

P: n/a
re********@yahoo.com (red floyd) wrote:
Now, I'm not the language guru that Victor is, and probably never will
be, but if the OP had used

#include <cstdio>

instead of

#include <stdio.h>

Wouldn't printf/fprintf be in the std namespace, so that there would
be no ambiguity between (the imported) herring::printf and
std::printf, while with the latter (as posted case), we have the
ambiguity between (the imported) herring::printf and ::printf


This was the intention of the standard but this was and is not common
practise: effectively, it is impossible to provide a standard C++ library
on top of a standard C library unless you have control over both which is
actually a rare case unless you drop the requirement of wrapping names in
namespace std. If I remember correctly, the standardization committee
recently removed the requirement that the C names are only in namespace
'std' if you include <cstdio>.

Actually, I argued that it should be possible to implement a standard C++
library on top of a standard C library and still get the names in namespace
'std'. This would look something like this - I thought:

// <cstdio>
namespace std {
#include "/usr/include/stdio.h"
}

// <stdio.h>
#include <cstdio>
using std::printf;
// ...

Unfortunately, this does not really work out: the standard C headers tend
to contain names which are not part of the standard C++ library. Thus,
something like this would not work:

#include <unistd.h>

because <unistd.h> internally includes some C library headers and cannot
resolve the corresponding names later. The alternative of using a using
statement rather than a using declaration, ie. 'using namespace std'
conflicts with requirements for other standard C++ library headers. The
third alternative, including "/usr/include/stdio.h" twice also does not
work:

// <stdio.h>
#include <cstdio> // for names in namespace std
#include "/usr/include/stdio.h" // for non-nested names

because the resulting types become incompatible:

FILE* fp = std::fopen("foo", "r");

Concerning the original problem, I would guess that there is no viable
solution.
--
<mailto:di***********@yahoo.com> <http://www.dietmar-kuehl.de/>
<http://www.contendix.com> - Software Development & Consulting
Jul 22 '05 #8

This discussion thread is closed

Replies have been disabled for this discussion.