// 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::wstring?
// class std::wstring; doesn't work.
VOID Boo(const MyClass& c);
VOID Foo(const std::wstring& s);
Форвардное объявление std:: wstring
Ответ 1
Вы не можете. #include <string>
, у вас (почти) нет выбора.
Причина в том, что wstring
определяется в пространстве имен std
и typedef'd до std::basic_string<wchar_t>
. Более подробно, std::wstring
- std::basic_string<wchar_t, std::char_traits<wchar_t> >
. Это означает, что для того, чтобы переслать-объявить std::wstring
, вам нужно будет переслать-объявить std::char_traits<>
и std::basic_string<>
внутри пространства имен std
. Поскольку (за исключением нескольких исключений) стандарт запрещает добавлять определения или декларации в пространство имен std
(17.4.3.1/1), в конечном счете вы не можете переадресовать любой стандартный шаблон или тип стандартным образом. В частности, это означает, что вы не можете переслать-объявить std::wstring
.
И да, мы все согласны с тем, что было бы удобно иметь заголовок <stringfwd>
, например <iosfwd>
для <iostream>
. Но нет. <string>
также не так сложно компилировать как <iostream>
, но тем не менее. У вас есть два варианта: #include<string>
или используйте непрозрачный указатель.
Ответ 2
std::wstring
- это экземпляр шаблона, поэтому вы не можете просто его объявить. Вам нужно будет использовать файл заголовка.
Ответ 3
Я не думаю, что избегать #include <string> дает вам какую-то реальную выгоду, но вот как вы могли это сделать:
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 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;
}
Вы должны быть осторожны с параметрами по умолчанию; в частности, это не сработало бы:
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>
Скомпилированный с включением показывает несовместимость:
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
Ответ 4
Вы не можете перенаправить объявление std::wstring
в соответствующую реализацию, а не потому, что это typedef
для template
специализации или что есть вероятность, что у него есть неизвестное количество аргументов шаблона (это не " t; они строго указаны), а потому, что существует ограничение на соответствующие программы, которые запрещают им добавлять какие-либо объявления или определения в пространство имен std
, отличное от явных специализаций стандартных шаблонов, которые специализируются на пользовательском типе.
Это ограничение указано в 17.4.3.1 [lib.reserved.names]/1. Не существует исключения для форвардных объявлений std::wstring
, вы должны #include <string>
сделать объявление std::wstring
доступным соответствующим образом.
Ответ 5
class std::wstring;
не компилируется. Но это делает:
namespace std{
class wstring;
}
Однако это объявление несовместимо с заголовочным файлом <string>
, который вы должны увидеть после #include <string>
после него. Так что это действительно не безопасно.