// This is a header file.
class MyClass; // It can be forward declared because the function uses reference.
// However, how can I do forward declaraion about std::wstri
class std::wstring;
doesn't compile. But this does:
namespace std{
class wstring;
}
However, this declaration is incompatible with the <string>
header file, which you should see if you #include <string>
after it. So it's really not safe.
You can't forward declare std::wstring
in a conforming implementation, not because it is a typedef
for a template
specialization or that there is any possibility that it has an unknown number of template arguments (it doesn't; these are strictly specified) but because there is a constraint on conforming programs that prohibits them from adding any declarations or definitions to the std
namespace other than explicit specializations of standard templates which are specialized on a user-defined type.
This constraint is stated in 17.4.3.1 [lib.reserved.names] / 1. There is no exception for forward declarations of std::wstring
, you must #include <string>
to make a declaration std::wstring
available in a conforming way.
I don't think avoiding #include <string> gains you any real benefit, but this is how you could do it:
namespace std {
template<class Char>
struct char_traits;
template<class T>
struct allocator;
template<class Char, class Traits, class Allocator>
struct basic_string;
typedef basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> >
wstring;
}
// simple test that it's compatible:
std::wstring *p; // incomplete type at this point, but you can have a pointer
#include <string>
int main() {
std::wstring s = L"Hello, world!";
p = &s;
return 0;
}
You have to be careful of default parameters; in particular, this would not work:
namespace std {
template<class Char>
struct char_traits;
template<class T>
struct allocator;
template<class Char, class Traits=char_traits<Char>,
class Allocator=allocator<Char> >
struct basic_string;
typedef basic_string<wchar_t> wstring;
}
#include <string>
Compiled with the include shows the incompatibility:
In file included from /usr/include/c++/4.4/string:41,
from example.cpp:15:
/usr/include/c++/4.4/bits/stringfwd.h:52: error: redefinition of default argument for ‘class _Traits’
example.cpp:8: note: original definition appeared here
You can't. #include <string>
, you have (almost) no choice.
The reason is that wstring
is defined in namespace std
and is typedef'd to std::basic_string<wchar_t>
. More elaborately, std::wstring
is std::basic_string<wchar_t, std::char_traits<wchar_t> >
. This means that in order to forward-declare std::wstring
you'd have to forward-declare std::char_traits<>
and std::basic_string<>
inside namespace std
. Because (apart from a few exceptions) the standard forbids adding definitions or declarations to namespace std
(17.4.3.1/1) ultimately you can't forward-declare any standard template or type in a standard-conforming way. Specifically, this means you can't forward-declare std::wstring
.
And yes, we all agree it would be convenient to have a <stringfwd>
header, like <iosfwd>
for <iostream>
. But there isn't. <string>
is also not nearly as hardcore to compile as <iostream>
, but nevertheless. You have two choices: #include<string>
or use an opaque pointer.
std::wstring
is a template instantiation, so you can't just forward declare it. You'll have to use the header file.