In C++11, it is definitely invalid to declare a vector of a class which is still an incomplete type right? I thought I could only use incomplete types as pointers, references, return types or parameter types. Searching (1) for "vector of incomplete type" suggests to me that containers of incomplete types should be an error (I'm using g++ version 4.8.1.). However the following code compiles fine on my system:
#ifndef SCREEN
#define SCREEN
#include <string>
using namespace std;
class Screen;
class Window_mgr{
public:
typedef vector<Screen>::size_type screenindex;
void clear(screenindex);
private:
vector<Screen> screens;
};
class Screen{
friend void Window_mgr::clear(screenindex);
public:
typedef string::size_type pos;
Screen() = default;
Screen(pos ht, pos wt): height(ht), width(wt), contents(ht*wt, ' ') { }
Screen(pos ht, pos wt, char c): height(ht), width(wt), contents(ht*wt, c) { }
private:
pos height = 0, width = 0;
pos cursor = 0;
string contents;
};
inline void Window_mgr::clear(screenindex i){
Screen& s = screens[i];
s.contents = string(s.height*s.width, ' ');
}
#endif // SCREEN
despite the fact Window_mgr declares a vector of Screens, which is still an incomplete type. These classes in my example are actually based on Chapter 7.3 of C++ Primer for any that have it. A question asked me to define my own versions of Screen and Window_mgr in which the member function clear is a member of Window_mgr and a friend of Screen. Except Window_mgr is also meant to contain a vector of Screens.
If creating a vector of an incomplete type IS invalid, how exactly would I do this using forward declarations? If I have a vector of screens in Window_mgr then its class definition must come after class Screen has already been defined. Except Screen must have a friend declaration of the clear member function of Window_mgr, but the following re-arrangement is an error because Screen uses the scope operator on an incomplete type;
class Window_mgr;
class Screen{
friend void Window_mgr::clear(screenindex);
public:
typedef string::size_type pos;
Screen() = default;
Screen(pos ht, pos wt): height(ht), width(wt), contents(ht*wt, ' ') { }
Screen(pos ht, pos wt, char c): height(ht), width(wt), contents(ht*wt, c) { }
private:
pos height = 0, width = 0;
pos cursor = 0;
string contents;
};
class Window_mgr{
public:
typedef vector<Screen>::size_type screenindex;
void clear(screenindex);
private:
vector<Screen> screens;
};
inline void Window_mgr::clear(screenindex i){
Screen& s = screens[i];
s.contents = string(s.height*s.width, ' ');
}
The only way I could think would be to replace the memberfunction friend declaration with a just friend declaration of the class
class Screen{
friend class Window_mgr;
// other stuff
}
but that's not what the question wants of me.