// filing.h //////////////////////////////////////////////////
// forward reference to avoid having to include <istream>
class istream;
void Read(istream& file, int& v);
void Read(istream& file, long& v);
void Read(istream& file, short& v);
// filing.cpp ///////////////////////////////////////////////////
#include "filing.h"
#include
using std::istream;
void Read(istream& file, int& v)
{
file >> v;
}
void Read(istream& file, long& v)
{
file >> v;
}
void Read(istream& file, short& v)
{
file >> v;
}
The error is:
using-declaration causes a multiple declaration of ''istream''
Now, I tried it with another class (std::string) and that gave a similar error (it was typedefed to String, so it just said "multiple definition of string" or something).
Why does this happen? Is it because istream is a template class or something? Is there a way around it?
Forward references
Ok, this fails to compile in both Visual C++ and Borland C++ Builder, so I assume it''s me that''s wrong and not the compilers. But I don''t understand why. Surely the forward declaration shouldn''t interfere with the actual definition?
I think what is happening is this: you are trying to declare a global class, then putting the std namespace into the global namespace, which causes a naming collision because there are now two `global namespace::string's (even though one is not defined yet).
In that case, try this:
That might not work either, considering istream is probably just a typedef for some variety of basic_istream. If that doesn't work, I'm not sure what you can do -- as far as I know you can't forward declare template classes (but maybe that's been changed?).
- null_pointer
Sabre Multimedia
Edited by - null_pointer on June 9, 2000 5:00:24 PM
In that case, try this:
namespace std {
class istream;
};
That might not work either, considering istream is probably just a typedef for some variety of basic_istream. If that doesn't work, I'm not sure what you can do -- as far as I know you can't forward declare template classes (but maybe that's been changed?).
- null_pointer
Sabre Multimedia
Edited by - null_pointer on June 9, 2000 5:00:24 PM
What is in your filing header - are you including something in there that declares istream?
I believe in VC++ you can open a brand new .cpp file and type
std::istream::read
and it know whats going on. So it might be pre-declaring something behind your back.
-Mezz
I believe in VC++ you can open a brand new .cpp file and type
std::istream::read
and it know whats going on. So it might be pre-declaring something behind your back.
-Mezz
A very easy way to have the appropriate forward declarations for the stream classes without having to include the whole class headers themselves is this:
That header file was specifically created for forward declarations, to help reduce compile times and such.
---- --- -- -
Blue programmer needs food badly. Blue programmer is about to die!
#include <iosfwd>
That header file was specifically created for forward declarations, to help reduce compile times and such.
---- --- -- -
Blue programmer needs food badly. Blue programmer is about to die!
OK, it -is- the fact that they are templates, as it works for non-template classes. Which is stupid, since if the C++ standard library pretty much relies on next to everything you use being a template in some form or other, this means you have to #include everything in your headers, even when just using pointers or references. This extremely bad on compile times.
Mossmoss, the <iosfwd> header works, thanks. Although having to include 44k of <iosfwd> compared to 15 bytes of 'class istream;' is very annoying. It's also just a hacked fix for these particular classes. The std::string usage, which I omitted from the original example for clarity but mentioned, still gives me these errors so I have to include it in its entirety anyway. And, guess what header file <string> includes? You guessed it, <istream>. Thus defeating the entire object. What a crap system.
Thanks all.
Edited by - Kylotan on June 9, 2000 10:16:51 PM
Mossmoss, the <iosfwd> header works, thanks. Although having to include 44k of <iosfwd> compared to 15 bytes of 'class istream;' is very annoying. It's also just a hacked fix for these particular classes. The std::string usage, which I omitted from the original example for clarity but mentioned, still gives me these errors so I have to include it in its entirety anyway. And, guess what header file <string> includes? You guessed it, <istream>. Thus defeating the entire object. What a crap system.
Thanks all.
Edited by - Kylotan on June 9, 2000 10:16:51 PM
The problem is that you created a forward declaration of class istream; however, istream is itself a typedef, not a class declaration.
So in order to get your forward declaration you need:
template <class _E, class _Tr = char_traits<_E> > class basic_istream;
typedef basic_istream<char, char_traits<char> > istream;
for the forward declarations and the typedefs. And furthermore you need to class defination of the char_traits class.
For forward declaring the string class you need:
template <class _E, class _Tr = char_traits<_E>, class _A = allocator<_E> > class basic_string;
typedef basic_string<char, char_traits<char>, allocator<char> > string;
as well as the class definition for the allocator class.
I suppose you could get away with doing forward declarations for the char_traits and the allocator classes though...
template <class _Ty> class allocator;
template <class _E> struct char_traits;
So in order to get your forward declaration you need:
template <class _E, class _Tr = char_traits<_E> > class basic_istream;
typedef basic_istream<char, char_traits<char> > istream;
for the forward declarations and the typedefs. And furthermore you need to class defination of the char_traits class.
For forward declaring the string class you need:
template <class _E, class _Tr = char_traits<_E>, class _A = allocator<_E> > class basic_string;
typedef basic_string<char, char_traits<char>, allocator<char> > string;
as well as the class definition for the allocator class.
I suppose you could get away with doing forward declarations for the char_traits and the allocator classes though...
template <class _Ty> class allocator;
template <class _E> struct char_traits;
I don't see why it should matter. At no point did I use an instance of the class, only a reference. Surely a reference will just be a simple 4-byte pointer like all the rest, no matter how the class is defined? Why does it need to know more than just that the class exists?
Edited by - Kylotan on June 10, 2000 1:24:08 PM
Edited by - Kylotan on June 10, 2000 1:24:08 PM
It doesn''t need to know anything more than the class exists. Here''s the deal. With the forward reference
class istream;
You entered into the symbol table a that there is a class type named istream. When the later typedef is made there is a collision because the typedef states that istream is an alias for basic_istream<char, char_traits<char> > and is therefore not a separate class. This fails under the structural equivelence for C++ and so causes a type error.
So the problem is that you have incompatible definitions for the meaning of the symbol "istream".
class istream;
You entered into the symbol table a that there is a class type named istream. When the later typedef is made there is a collision because the typedef states that istream is an alias for basic_istream<char, char_traits<char> > and is therefore not a separate class. This fails under the structural equivelence for C++ and so causes a type error.
So the problem is that you have incompatible definitions for the meaning of the symbol "istream".
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement