Way to pre-declare standard templated class types?

Started by
11 comments, last by wintertime 11 years, 1 month ago

I wonder if GCC has a non-standard built-in pre-declaration header somewhere that it uses internally - I'll look around.

<bits/strfwd.h> in GCC and MinGW pre-declares std::string, std::wstring, std::u16string, std::u32string. Though it says:


/** @file bits/stringfwd.h
* This is an internal header file, included by other library headers.
* Do not attempt to use it directly. @headername{string}
*/


Based on RobTheBloke's code a few posts up, this is the header I'm going to start using: (works with MinGW 4.7.2)


#ifndef COMMON_SYSTEM_FWDSTRING_H
#define COMMON_SYSTEM_FWDSTRING_H

/*
	Forward-declares std::string, StringList, and StringMap.
	
	WARNING: This is non-standard.
*/

namespace std
{
	//----------------------------------------------------------------------
	//	Forward-declare std::string (and std::char_traits, and std::allocator)
	
	template < class T > struct char_traits;
	template < typename T > class allocator;
	template < typename CharT, typename Traits, typename Alloc = allocator<CharT> > class basic_string;

	typedef basic_string<char,		char_traits<char>,		allocator<char> >		string;
	typedef basic_string<wchar_t,	char_traits<wchar_t>,	allocator<wchar_t> >	wstring;
	typedef basic_string<char16_t,	char_traits<char16_t>,	allocator<char16_t> >	u16string;
	typedef basic_string<char32_t,	char_traits<char32_t>,	allocator<char32_t> >	u32string;

	//----------------------------------------------------------------------
	//	Forward-declare std::vector.

	template < class T, class Alloc > class vector;
	
	//----------------------------------------------------------------------
	//	Forward-declare std::less, std::pair, and std::map.

	template <class T> struct less;
	template <class T1, class T2> struct pair;

	template < class Key, class T, class Compare, class Alloc > class map;
	
	//----------------------------------------------------------------------
}

typedef std::vector<std::string, std::allocator<std::string> > StringList;
typedef std::map<std::string, std::string, std::less<std::string>, std::allocator<std::pair<std::string, std::string> > > StringMap;

#endif // COMMON_SYSTEM_FWDSTRING_H


GCC will lets me pre-declare the templated classes, but won't let me have default template arguments, because later when the actual templated class is defined, it complains about "redefinition of default argument", which is why I manually declared std::basic_string<char, char_traits<char>, allocator<char> >, instead of just std::basic_string<char>.

Advertisement


- If you are trying to solve circular dependencies... SAY WHAT?

It happens, especially when working in large teams. It shouldn't happen, and there is usually a way to fix them 'properly', but when deadlines are tight, it's usually better to get it out of the door no matter what, than refactor vasts swathes of code (and go through another round of QA/bug-fixing/delayed release).


I was specifically referencing circular dependencies with respect to the standard library - you can't really cause that without editing your standard library headers...

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]


#include <iosfwd>

That is at least standard and you would get the string indirectly too.

For everything else just try to move as many includes into the .cpp files and remove not needed and redundant headers that get included indirectly already.

Then look if you can not show some of your own types in some headers if you only need references or pointers.

Then maybe use abstract base classes and only include all low level stuff in a derived class.

Oh and try to not include windows.h in your header files and define that WIN32_LEAN_AND_MEAN before that so there is less things included.

This topic is closed to new replies.

Advertisement