Search code examples
c++templatesinheritanceforward-declarationstdstring

forward declaration of std::string and std::wstring


The problem of the inability to forward declare std::string and std::wstring is often discussed. As I understand, the reason is that those types are typedefing of instantiation of template class basic_string:

namespace std {
  typedef basic_string<char>    string;
  typedef basic_string<wchar_t> wstring;
}

And forward declaration of a typedef isn't allowed by the language.

Wouldn't it be better for the c++ standard using inheritance instead of typedef:

namespace std {
  class string : public basic_string<char> {};
  class wstring : public basic_string<wchar_t> {};
}

So that way we could forward declare std::string and std::wstring?


Solution

  • Wouldn't be better for the c++ standard using inheritance instead of typedef [...]

    No.

    The std::basic_string is not meant to be inherited in any form. This limitation allows the implementation of a std::basic_string, that is much cheaper (faster) to create and destroy, as it has no virtual function table.

    If you need std::[w]string to be defined, just #include it.

    Edit (answering comment)

    One of the guiding principles of C++ (and the standard library) is "do not pay for what you do not use". This means the code is written in such a way, that you should not incur runtime costs for features you do not need.

    Creating a std::string instance would be much more expensive if each instance had a virtual table (and this would make using std::string, prohibitive in performance-critical code).

    Instead, std::string is intended as a fast, type-safe, RAII implementation of the C char* mechanism. Similarly, you should not attempt to inherit from std::vector, list, map, shared_ptr, unique_ptr and so on.

    If you really need a string base class, consider writing a your_namespace::[w]string_base yourself (a trivial implementation would be one that encapsulates a std::[w]string internally).