468,107 Members | 1,301 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,107 developers. It's quick & easy.

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::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
Jul 22 '05 #1
6 4541
"Steven T. Hatton" <su******@setidava.kushan.aa> wrote in
news:gN********************@speakeasy.net:
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":


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

Jul 22 '05 #2
Andre Kostur wrote:
ostream isn't a simple class... you may want to include <iosfwd>
instead...


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
Jul 22 '05 #3
"Steven T. Hatton" <su******@setidava.kushan.aa> wrote in message news:<78********************@speakeasy.net>...
Andre Kostur wrote:
ostream isn't a simple class... you may want to include <iosfwd>
instead...
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.


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
//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);
}

Jul 22 '05 #4
Dave Moore wrote:
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;
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.
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:
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

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

should remove the need to include <valarray> in your header file.


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
Jul 22 '05 #5
"Steven T. Hatton" <su******@setidava.kushan.aa> wrote in message news:<fa********************@speakeasy.net>...
Dave Moore wrote:
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;
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.


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


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:

[snip]

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

#ifndef FORWARD_HPP
#define FORWARD_HPP

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

namespace std{
template<class> class valarray;
}
[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.
I have to wonder how many problems exist with the 'solution' I presented
above.


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

HTH, Dave Moore
Jul 22 '05 #6
dt*****@rijnh.nl (Dave Moore) wrote in message news:<30**************************@posting.google. com>...
"Steven T. Hatton" <su******@setidava.kushan.aa> wrote in message news:<fa********************@speakeasy.net>...
Dave Moore wrote:
[snip]
/*************
forward.hpp
/*************

#ifndef FORWARD_HPP
#define FORWARD_HPP

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

namespace std{
template<class> class valarray;
}
[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.


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


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]
I have to wonder how many problems exist with the 'solution' I presented
above.


Sorry for the misunderstanding earlier ...

HTH, Dave Moore
Jul 22 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

1 post views Thread by matthew polder | last post: by
3 posts views Thread by mjm | last post: by
4 posts views Thread by whithers | last post: by
11 posts views Thread by aleko | last post: by
23 posts views Thread by mark.moore | last post: by
10 posts views Thread by collection60 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.