Предварительное объявление std :: wstring - PullRequest
20 голосов
/ 26 января 2011
// 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);

Ответы [ 5 ]

35 голосов
/ 26 января 2011

Вы не можете. #include <string>, у вас (почти) нет выбора.

Причина в том, что wstring определено в пространстве имен std и имеет typedef'd to 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> или использовать непрозрачный указатель .

3 голосов
/ 26 января 2011

Я не думаю, что отказ от #include принесет вам реальную выгоду, но вот как вы можете это сделать:

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

Вы должны быть осторожны с параметрами по умолчанию;в частности, это не будет работать:

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
3 голосов
/ 26 января 2011

std::wstring является экземпляром шаблона, поэтому вы не можете просто объявить его. Вам придется использовать файл заголовка.

2 голосов
/ 26 января 2011

Вы не можете пересылать объявление std::wstring в соответствующей реализации, не потому, что это typedef для template специализации или что есть вероятность, что у него есть неизвестное количество аргументов шаблона (это не ' t; они строго определены), но существует ограничение на соответствующие программы, которое запрещает им добавлять любые объявления или определения в пространство имен std, кроме явных специализаций стандартных шаблонов, которые специализируются на определяемом пользователем типе.

Это ограничение указано в 17.4.3.1 [lib.reserved.names] / 1. Для предварительных объявлений std::wstring не существует исключения, вы должны #include <string>, чтобы сделать объявление std::wstring доступным соответствующим образом. .

0 голосов
/ 26 января 2011

class std::wstring; не компилируется. Но это делает:

namespace std{
class wstring;
}

Однако это объявление несовместимо с заголовочным файлом <string>, который вы должны увидеть, если после него #include <string>. Так что это действительно небезопасно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...