简体   繁体   中英

templated circular inheritance

in this code, compiler complain about undefined MyClassB , which is understandable :

class MyClassA;
class MyClassB;

template <class T> class BaseClass : public T {
};

class MyClassA : public BaseClass<MyClassB> {
};

class MyClassB : public BaseClass<MyClassA> {
};

but in this code, compile is successful and no complain about MyClassB :

class MyClassA;
class MyClassB;

template <class T> class BaseClass : public T {
};

class MyClassA : public BaseClass<std::vector<MyClassB>> {
};

class MyClassB : public BaseClass<std::vector<MyClassA>> {
};

why the second code compile, since MyClassB is not yet defined when constructing std::vector<MyClassB> ?

Because your implementation of std::vector allows an incomplete type. This is a side effect of the instantiation rules of member functions of class templates: they aren't instantiated until they're used. So the functions that do need it to be a complete type aren't instantiated, yet. So no errors.

Contrarily, it does need to be a complete type to be a base class, so you get an error in that case.


However, it's actually undefined behavior to pass an incomplete type to std::vector (or any other standard library container), and "it works" is a valid undefined outcome. You shouldn't do it.

Lookup the " Curiously Recurring Template Pattern ".

Your BaseClass class uses its template argument as a base class, which requires a complete type.

The second version of the code just passes the template argument to another template, an incomplete type is allowed in that case, if the second template doesn't do anything requiring a complete type. If you used the argument in any way that required a complete type, it wouldn't be allowed either.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM