overloading std C functions with a namespace

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • zbyszek@amtp.liv.ac.uk

    overloading std C functions with a namespace

    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::fprint f;

    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::fprint f;
    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::halibu t()':
    name.C:15: call of overloaded `fprintf(FILE*& , const char[5])' is
    ambiguous
    name.C:5: candidates are: int herring::fprint f(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::fprint f;

    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::fprint f; 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.
  • Victor Bazarov

    #2
    Re: overloading std C functions with a namespace

    <zbyszek@amtp.l iv.ac.uk> wrote...[color=blue]
    > 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::fprint f;
    >
    > 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::fprint f;
    > 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::halibu t()':
    > name.C:15: call of overloaded `fprintf(FILE*& , const char[5])' is
    > ambiguous
    > name.C:5: candidates are: int herring::fprint f(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::fprint f;
    >
    > 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::fprint f; 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?[/color]

    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


    Comment

    • red floyd

      #3
      Re: overloading std C functions with a namespace

      "Victor Bazarov" <v.Abazarov@com Acast.net> wrote in message news:<eNcqc.166 05$qA.2058485@a ttbi_s51>...[color=blue]
      > [redacted][/color]

      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

      Comment

      • Victor Bazarov

        #4
        Re: overloading std C functions with a namespace

        red floyd wrote:[color=blue]
        > "Victor Bazarov" <v.Abazarov@com Acast.net> wrote in message news:<eNcqc.166 05$qA.2058485@a ttbi_s51>...
        >[color=green]
        >>[redacted][/color]
        >
        >
        > 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[/color]

        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

        Comment

        • Jerry Coffin

          #5
          Re: overloading std C functions with a namespace

          zbyszek@amtp.li v.ac.uk wrote in message news:<c8aodt$89 h$1@news.liv.ac .uk>...[color=blue]
          > 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::fprint f;[/color]

          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::fprint f;
          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.

          Comment

          • tom_usenet

            #6
            Re: overloading std C functions with a namespace

            On Tue, 18 May 2004 09:20:55 -0400, Victor Bazarov
            <v.Abazarov@com Acast.net> wrote:
            [color=blue]
            >red floyd wrote:[color=green]
            >> "Victor Bazarov" <v.Abazarov@com Acast.net> wrote in message news:<eNcqc.166 05$qA.2058485@a ttbi_s51>...
            >>[color=darkred]
            >>>[redacted][/color]
            >>
            >>
            >> 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[/color]
            >
            >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.[/color]

            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

            Comment

            • zbyszek@amtp.liv.ac.uk

              #7
              Re: overloading std C functions with a namespace

              Thanks for your interest and interesting comments...
              [color=blue][color=green]
              >>red floyd wrote:[color=darkred]
              >>> "Victor Bazarov" <v.Abazarov@com Acast.net> wrote in message news:<eNcqc.166 0[/color][/color]
              >5$qA.2058485@a ttbi_s51>...[color=green][color=darkred]
              >>>
              >>>>[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[/color][/color][/color]

              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.
              [color=blue][color=green]
              >>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.[/color]
              >
              >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.
              >}[/color]

              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.

              Comment

              • Dietmar Kuehl

                #8
                Re: overloading std C functions with a namespace

                redfloyd11@yaho o.com (red floyd) wrote:[color=blue]
                > 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[/color]

                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:dietmar _kuehl@yahoo.co m> <http://www.dietmar-kuehl.de/>
                <http://www.contendix.c om> - Software Development & Consulting

                Comment

                Working...