Connecting Tech Pros Worldwide Help | Site Map

forward declarations and namespaces?

Steven T. Hatton
Guest
 
Posts: n/a
#1: Jul 22 '05
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::runTest(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::runTest(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
Guest
 
Posts: n/a
#2: Jul 22 '05

re: forward declarations and namespaces?


"Steven T. Hatton" <susudata@setidava.kushan.aa> wrote in
news:gN-dnbQM24qrdBDd4p2dnA@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::runTest(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...

Steven T. Hatton
Guest
 
Posts: n/a
#3: Jul 22 '05

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:
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.


//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.hpp"

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

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


//main.cc
#include "forward.hpp"
#include <iostream>
int main(int argc, char* argv[]) {
V v(10);
std::cout<<v.stringify(std::cout);
}


--
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
Dave Moore
Guest
 
Posts: n/a
#4: Jul 22 '05

re: forward declarations and namespaces?


"Steven T. Hatton" <susudata@setidava.kushan.aa> wrote in message news:<78ydnVZ_L4a_hw3dRVn-hg@speakeasy.net>...[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.hpp"
>
> V::V(const size_t& size){
> va = new valarray<double>(1.1,size);
> }
>
> std::ostream& V::stringify(std::ostream& out){
> for(size_t i = 0; i < va->size(); i++)
> {
> out << (*va)[i] << " ";
> }
> return out;
> }
>
>
> //main.cc
> #include "forward.hpp"
> #include <iostream>
> int main(int argc, char* argv[]) {
> V v(10);
> std::cout<<v.stringify(std::cout);
> }[/color]
Steven T. Hatton
Guest
 
Posts: n/a
#5: Jul 22 '05

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.hpp"
#include <iostream>
#include <valarray>

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

std::ostream& V::stringify(std::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<double>* va;
std::ostream& stringify(std::ostream& out);
};

#endif



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

#include "forward.hpp"
#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(ostream& out)=0;
};

inline ostream& operator<<(ostream& 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
Dave Moore
Guest
 
Posts: n/a
#6: Jul 22 '05

re: forward declarations and namespaces?


"Steven T. Hatton" <susudata@setidava.kushan.aa> wrote in message news:<fa-dnc_AP646CQzdRVn-sA@speakeasy.net>...[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
Dave Moore
Guest
 
Posts: n/a
#7: Jul 22 '05

re: forward declarations and namespaces?


dtmoore@rijnh.nl (Dave Moore) wrote in message news:<306d400f.0404300226.36fc27ac@posting.google. com>...[color=blue]
> "Steven T. Hatton" <susudata@setidava.kushan.aa> wrote in message news:<fa-dnc_AP646CQzdRVn-sA@speakeasy.net>...[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 misunderstanding earlier ...

HTH, Dave Moore
Closed Thread