Forward declaration of std::wstring

前端 未结 5 1979
忘了有多久
忘了有多久 2021-02-05 08:00
// 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         


        
相关标签:
5条回答
  • 2021-02-05 08:07

    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.

    0 讨论(0)
  • 2021-02-05 08:09

    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.

    0 讨论(0)
  • 2021-02-05 08:22

    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
    
    0 讨论(0)
  • 2021-02-05 08:24

    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.

    0 讨论(0)
  • 2021-02-05 08:29

    std::wstring is a template instantiation, so you can't just forward declare it. You'll have to use the header file.

    0 讨论(0)
提交回复
热议问题