473,397 Members | 1,985 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,397 software developers and data experts.

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 5174
"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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: matthew polder | last post by:
Hi, I have two libraries that used different namespaces, call them "fruit" and "vegetable." In one of the class definitions of fruit, I have the following. class corn; //This doesn't work. ...
3
by: mjm | last post by:
Folks, Please help me with the following problems: ******************************************** 1. I have a class template template<class Base> class Matrix : public Base { /* .... */ }
4
by: whithers | last post by:
How do I do forward declarations when namespaces are involved? For example, given the following: -------------------------------------ClassA.h #ifndef CLASSA_H #define CLASSA_H namespace...
11
by: aleko | last post by:
This applies equally to function prototypes. Why do we have to tell the compiler twice? Other modern compiled languages don't have this requirement. Just curious, Aleko
23
by: mark.moore | last post by:
I know this has been asked before, but I just can't find the answer in the sea of hits... How do you forward declare a class that is *not* paramaterized, but is based on a template class? ...
8
by: Simon Brooke | last post by:
I was debugging a new XML generator tonight and trying to determine why it wasn't working; and realised my dom printer does not output XML namespace declarations. My method to output an Element...
1
by: ctor | last post by:
Hi, I'm experimenting with using a lot of different namespaces in my current project to see if it helps me keep my code more organized. In some ways I'm finding that it causes more problems...
10
by: collection60 | last post by:
Will C++ ever have Java-like multiple level compiling? So that we can dump the old model of having to first declare then write the code? I find the declaration wastes so much time in coding....
10
by: Andy Fish | last post by:
hi, I have an XSLT which is producing XML output. many of the nodes in the output tree contain namespace declarations for namespaces that are used in the source document even though they are...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.