forward declarations and namespaces?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Steven T. Hatton

    forward declarations and namespaces?

    Should I be able to forward declare something from a namespace different
    from the current one? For example the following code compiles:

    //testdriver.hpp
    #ifndef TESTDRIVER_HPP
    #define TESTDRIVER_HPP
    #include <ostream>

    namespace ns_testdriver{
    using std::ostream;

    class Testdriver{
    public:
    Testdriver(){}
    virtual ~Testdriver(){}
    virtual void runTest(ostream & out);
    };
    }
    #endif

    /*************** *************** */

    //testdriver.cpp
    #include "testdriver.hpp "

    namespace ns_testdriver{

    void Testdriver::run Test(ostream& out){
    out << "This is ns_testdriver:: Testdriver";
    }
    }


    When I tried to forward declare std::ostream in testdriver.hpp I couldn't
    figure out a way that would compile. Is this the wrong thing to try to do,
    or am I just screwing it up?

    The following code is one example of the different things I've tried. It
    results in "error: `ostream' is already declared in this scope":

    //testdriver.hpp
    #ifndef TESTDRIVER_H
    #define TESTDRIVER_H

    namespace ns_testdriver{
    using namespace std;
    class ostream;

    class Testdriver{
    public:
    Testdriver(){}
    virtual ~Testdriver(){}
    virtual void runTest(ostream & out);
    };
    }
    #endif

    /*************** *************** */
    //testdriver.cpp
    #include "testdriver.hpp "
    #include <ostream>

    namespace ns_testdriver{
    using std::ostream;
    void Testdriver::run Test(ostream& out){
    out << "This is ns_testdriver:: Testdriver";
    }
    }
    --
    STH
    Hatton's Law: "There is only One inviolable Law"
    KDevelop: http://www.kdevelop.org SuSE: http://www.suse.com
    Mozilla: http://www.mozilla.org
  • Andre Kostur

    #2
    Re: forward declarations and namespaces?

    "Steven T. Hatton" <susudata@setid ava.kushan.aa> wrote in
    news:gN-dnbQM24qrdBDd4p 2dnA@speakeasy. net:
    [color=blue]
    > Should I be able to forward declare something from a namespace
    > different from the current one? For example the following code
    > compiles:
    >
    > //testdriver.hpp
    > #ifndef TESTDRIVER_HPP
    > #define TESTDRIVER_HPP
    > #include <ostream>
    >
    > namespace ns_testdriver{
    > using std::ostream;
    >
    > class Testdriver{
    > public:
    > Testdriver(){}
    > virtual ~Testdriver(){}
    > virtual void runTest(ostream & out);
    > };
    > }
    > #endif
    >
    > /*************** *************** */
    >
    > //testdriver.cpp
    > #include "testdriver.hpp "
    >
    > namespace ns_testdriver{
    >
    > void Testdriver::run Test(ostream& out){
    > out << "This is ns_testdriver:: Testdriver";
    > }
    > }
    >
    >
    > When I tried to forward declare std::ostream in testdriver.hpp I
    > couldn't figure out a way that would compile. Is this the wrong thing
    > to try to do, or am I just screwing it up?
    >
    > The following code is one example of the different things I've tried.
    > It results in "error: `ostream' is already declared in this scope":[/color]

    ostream isn't a simple class... you may want to include <iosfwd>
    instead...

    Comment

    • Steven T. Hatton

      #3
      Re: forward declarations and namespaces?

      Andre Kostur wrote:
      [color=blue]
      > ostream isn't a simple class... you may want to include <iosfwd>
      > instead...[/color]

      My difficulties may be the result of a pedantic compiler. Even this example
      from Stroustrup's TC++PL fails on gcc 3.40:


      The compiler is correctly conforming to the Standard. See here for more
      inof:



      <iosfwd> /Did/ work correctly for me. However, I now find the same problem
      with /valarray/. The code listed below compiles and runs. Note, however,
      <valarray> is #included in /forward.hpp/ rather than the implementation
      file.


      //forward.hpp
      #ifndef FORWARD_HPP
      #define FORWARD_HPP

      #include <iosfwd>
      #include <valarray>

      using std::valarray;

      struct V{
      V(const size_t& size);
      valarray<double >* va;
      std::ostream& stringify(std:: ostream& out);
      };

      #endif


      //forward.cc
      #include <iostream>
      #include <valarray>
      #include "forward.hp p"

      V::V(const size_t& size){
      va = new valarray<double >(1.1,size);
      }

      std::ostream& V::stringify(st d::ostream& out){
      for(size_t i = 0; i < va->size(); i++)
      {
      out << (*va)[i] << " ";
      }
      return out;
      }


      //main.cc
      #include "forward.hp p"
      #include <iostream>
      int main(int argc, char* argv[]) {
      V v(10);
      std::cout<<v.st ringify(std::co ut);
      }


      --
      STH
      Hatton's Law: "There is only One inviolable Law"
      KDevelop: http://www.kdevelop.org SuSE: http://www.suse.com
      Mozilla: http://www.mozilla.org

      Comment

      • Dave Moore

        #4
        Re: forward declarations and namespaces?

        "Steven T. Hatton" <susudata@setid ava.kushan.aa> wrote in message news:<78ydnVZ_L 4a_hw3dRVn-hg@speakeasy.ne t>...[color=blue]
        > Andre Kostur wrote:
        >[color=green]
        > > ostream isn't a simple class... you may want to include <iosfwd>
        > > instead...[/color]
        >
        > My difficulties may be the result of a pedantic compiler. Even this example
        > from Stroustrup's TC++PL fails on gcc 3.40:
        > http://www.research.att.com/~bs/matrix.c
        >
        > The compiler is correctly conforming to the Standard. See here for more
        > inof:
        > http://gcc.gnu.org/ml/gcc/2004-04/msg01269.html
        >
        >
        > <iosfwd> /Did/ work correctly for me. However, I now find the same problem
        > with /valarray/. The code listed below compiles and runs. Note, however,
        > <valarray> is #included in /forward.hpp/ rather than the implementation
        > file.
        >[/color]

        As with std::ostream, std::valarray is not a simple class type,
        therefore, an attempt to forward declare it like:

        using namespace std;
        class valarray;

        will fail. Unfortunately there is AFAIK no mechanism like <iosfwd>
        providing forward declarations of other STL classes. OTOH, you can
        probably roll your own by looking at the examples in <iosfwd> ...
        without checking myself, I expect something like:

        using namespace std;
        template <class T> class valarray;

        should remove the need to include <valarray> in your header file.
        IIRC, std::valarray takes only one template argument.

        HTH, Dave Moore
        [color=blue]
        > //forward.hpp
        > #ifndef FORWARD_HPP
        > #define FORWARD_HPP
        >
        > #include <iosfwd>
        > #include <valarray>
        >
        > using std::valarray;
        >
        > struct V{
        > V(const size_t& size);
        > valarray<double >* va;
        > std::ostream& stringify(std:: ostream& out);
        > };
        >
        > #endif
        >
        >
        > //forward.cc
        > #include <iostream>
        > #include <valarray>
        > #include "forward.hp p"
        >
        > V::V(const size_t& size){
        > va = new valarray<double >(1.1,size);
        > }
        >
        > std::ostream& V::stringify(st d::ostream& out){
        > for(size_t i = 0; i < va->size(); i++)
        > {
        > out << (*va)[i] << " ";
        > }
        > return out;
        > }
        >
        >
        > //main.cc
        > #include "forward.hp p"
        > #include <iostream>
        > int main(int argc, char* argv[]) {
        > V v(10);
        > std::cout<<v.st ringify(std::co ut);
        > }[/color]

        Comment

        • Steven T. Hatton

          #5
          Re: forward declarations and namespaces?

          Dave Moore wrote:
          [color=blue]
          > As with std::ostream, std::valarray is not a simple class type,
          > therefore, an attempt to forward declare it like:
          >
          > using namespace std;
          > class valarray;[/color]

          I didn't even want to introduce the namespace at that point. I find
          the /using/ directive for namespaces to be contrary to my sense of order.
          I much prefer introducing specific names as needed with /using/
          declaration.
          [color=blue]
          > will fail. Unfortunately there is AFAIK no mechanism like <iosfwd>
          > providing forward declarations of other STL classes. OTOH, you can
          > probably roll your own by looking at the examples in <iosfwd> ...
          > without checking myself, I expect something like:[/color]

          I used something that I'm pretty sure is either explicitly undefined, or
          non-conforming by introducing my own names into std:: This is the whole
          ugly solution I cam up with:

          /*************
          Makefile
          /*************
          forward : forward.hpp forward.cc main.cc
          g++ -o forward forward.cc main.cc
          clean:
          rm *.o forward



          /*************
          forward.cc
          /*************

          #include "forward.hp p"
          #include <iostream>
          #include <valarray>

          V::V(const size_t& size){
          va = new std::valarray<d ouble>(1.1,size );
          }

          std::ostream& V::stringify(st d::ostream& out){
          for(size_t i = 0; i < va->size(); i++)
          {
          out << (*va)[i] << " ";
          }
          return out;
          }



          /*************
          forward.hpp
          /*************

          #ifndef FORWARD_HPP
          #define FORWARD_HPP

          #include <iosfwd>
          #include "stringable.hpp "

          namespace std{
          template<class> class valarray;
          }

          struct V: public Stringable {
          V(const size_t& size);
          std::valarray<d ouble>* va;
          std::ostream& stringify(std:: ostream& out);
          };

          #endif



          /*************
          main.cc
          /*************

          #include "forward.hp p"
          #include <iostream>

          int main(int argc, char* argv[]) {
          V v(10);
          std::cout << v << "\n";
          }



          /*************
          stringable.hpp
          /*************

          #ifndef STRINGABLE_H
          #define STRINGABLE_H
          #include <iosfwd>

          using std::ostream;

          /**
          An un-universal base class
          */
          class Stringable {
          public:
          virtual ostream& stringify(ostre am& out)=0;
          };

          inline ostream& operator<<(ostr eam& out, Stringable& s){
          s.stringify(out );
          return out;
          }

          #endif



          [color=blue]
          > using namespace std;
          > template <class T> class valarray;
          >
          > should remove the need to include <valarray> in your header file.[/color]

          That is, if I have std:: available from some other #include. As You see
          from the code above, I actually opened the std namespace up, and put my own
          forwar declaration in there.

          I have to wonder how many problems exist with the 'solution' I presented
          above.


          --
          STH
          Hatton's Law: "There is only One inviolable Law"
          KDevelop: http://www.kdevelop.org SuSE: http://www.suse.com
          Mozilla: http://www.mozilla.org

          Comment

          • Dave Moore

            #6
            Re: forward declarations and namespaces?

            "Steven T. Hatton" <susudata@setid ava.kushan.aa> wrote in message news:<fa-dnc_AP646CQzdRV n-sA@speakeasy.ne t>...[color=blue]
            > Dave Moore wrote:
            >[color=green]
            > > As with std::ostream, std::valarray is not a simple class type,
            > > therefore, an attempt to forward declare it like:
            > >
            > > using namespace std;
            > > class valarray;[/color]
            >
            > I didn't even want to introduce the namespace at that point. I find
            > the /using/ directive for namespaces to be contrary to my sense of order.
            > I much prefer introducing specific names as needed with /using/
            > declaration.[/color]

            Ok I understand this ... I also balk at 'using' the whole std
            namespace in a header file. I used to do it, but it caused some weird
            problems that I never tracked down all the way, but which went away
            when I switched to only putting 'using namespace std' in .cpp files.
            That was a while ago with an old version of GCC, but I stuck with the
            habit. Lately I have also started introducing specific names when
            writing headers containing templates.
            [color=blue][color=green]
            > > will fail. Unfortunately there is AFAIK no mechanism like <iosfwd>
            > > providing forward declarations of other STL classes. OTOH, you can
            > > probably roll your own by looking at the examples in <iosfwd> ...
            > > without checking myself, I expect something like:[/color]
            >
            > I used something that I'm pretty sure is either explicitly undefined, or
            > non-conforming by introducing my own names into std:: This is the whole
            > ugly solution I cam up with:
            >[/color]
            [snip]
            [color=blue]
            >
            > /*************
            > forward.hpp
            > /*************
            >
            > #ifndef FORWARD_HPP
            > #define FORWARD_HPP
            >
            > #include <iosfwd>
            > #include "stringable.hpp "
            >
            > namespace std{
            > template<class> class valarray;
            > }[/color]

            [snip]

            I don't see any problem with the declaration above .. you have not
            injected your own name into the std namespace, you have simply
            provided a forward declaration of an existing STL container with the
            proper syntax. I don't see how this breaks anything, because if you
            screw up the forward declaration, you will get a bucketful of
            compile-time errors when you include the proper STL header in your
            ..cpp file. I checked this using GCC 3.3.1 by forward declaring
            std::valarray with two template parameters, or std::vector with 1
            template parameter, and did indeed get the compile-time errors. Now,
            redefining std::valarray would definitely be a no-no, but declaring it
            like you did above seems fine. BTW, I would probably comment every
            such forward declaration to clarify your intent.
            [color=blue]
            > I have to wonder how many problems exist with the 'solution' I presented
            > above.[/color]

            None AFAICS, at least not with the forward declaration of
            std::valarray.

            HTH, Dave Moore

            Comment

            • Dave Moore

              #7
              Re: forward declarations and namespaces?

              dtmoore@rijnh.n l (Dave Moore) wrote in message news:<306d400f. 0404300226.36fc 27ac@posting.go ogle.com>...[color=blue]
              > "Steven T. Hatton" <susudata@setid ava.kushan.aa> wrote in message news:<fa-dnc_AP646CQzdRV n-sA@speakeasy.ne t>...[color=green]
              > > Dave Moore wrote:[/color][/color]

              [snip]
              [color=blue][color=green]
              > > /*************
              > > forward.hpp
              > > /*************
              > >
              > > #ifndef FORWARD_HPP
              > > #define FORWARD_HPP
              > >
              > > #include <iosfwd>
              > > #include "stringable.hpp "
              > >
              > > namespace std{
              > > template<class> class valarray;
              > > }[/color]
              >
              > [snip]
              >
              > I don't see any problem with the declaration above .. you have not
              > injected your own name into the std namespace, you have simply
              > provided a forward declaration of an existing STL container with the
              > proper syntax.[/color]

              Ok .. I was just re-reading some of the "Guru of the Week" questions,
              and it turns out that the above statement is incorrect .. (c.f. GotW
              #34 http://www.gotw.ca/gotw/034.htm )
              [color=blue]
              > I don't see how this breaks anything, because if you
              > screw up the forward declaration, you will get a bucketful of
              > compile-time errors when you include the proper STL header in your
              > .cpp file. I checked this using GCC 3.3.1 by forward declaring
              > std::valarray with two template parameters, or std::vector with 1
              > template parameter, and did indeed get the compile-time errors.[/color]

              So, what I have said above is technically correct, but it makes your
              code completely non-portable, and also susceptible to (otherwise
              transparent) changes to the STL implementation in later compiler
              versions.

              [snip]
              [color=blue][color=green]
              > > I have to wonder how many problems exist with the 'solution' I presented
              > > above.[/color][/color]

              Sorry for the misunderstandin g earlier ...

              HTH, Dave Moore

              Comment

              Working...