std :: wstring的前向声明

时间:2011-01-26 04:29:09

标签: c++ stl forward-declaration

// 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 个答案:

答案 0 :(得分:35)

你做不到。 #include <string>,你几乎没有选择。

原因是wstring在名称空间std中定义,并且是std::basic_string<wchar_t>的typedef。更详细地说,std::wstringstd::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>或使用opaque pointer

答案 1 :(得分:3)

std::wstring是一个模板实例化,所以你不能只是转发声明它。你必须使用头文件。

答案 2 :(得分:3)

我不认为避免#include&lt; string&gt;为您带来任何实际利益,但这就是您可以做到的:

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>

使用include编译显示不兼容性:

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 :(得分:2)

您无法在符合要求的实施中转发声明std::wstring,而不是因为typedef专业化是template,或者它有可能是未知数量的std模板参数(它没有;严格指定这些参数),但因为对符合程序的约束禁止它们向std::wstring命名空间添加任何声明或定义,而不是专门用于标准模板的显式特化用户定义的类型。

此约束在17.4.3.1 [lib.reserved.names] / 1中说明。#include <string>的前向声明没有例外,您必须std::wstring进行声明{{1}以合规的方式提供。

答案 4 :(得分:-2)

class std::wstring;无法编译。但这样做:

namespace std{
class wstring;
}

但是,此声明不兼容<string>标头文件,如果您#include <string>之后,您应该看到该文件。所以这真的不安全。