Wt recommends to use forward declarations to avoid circular dependencies.
// Settings.h
#include <Wt/Dbo/Dbo.h>
#include <string>
class User; // Forward declaration of User Wt::Dbo object
class Settings
{
public:
Wt::Dbo::ptr<User> user;
template<class Action>
void persist(Action& a)
{
Wt::Dbo::belongsTo(a, user);
}
};
// User.h
#include <Wt/Dbo/Dbo.h>
#include <string>
#include "Settings.h"
class User
{
public:
Wt::Dbo::weak_ptr<Settings> settings;
template<class Action>
void persist(Action& a)
{
Wt::Dbo::hasOne(a, settings);
}
};
However, when I use this Settings
class in another cpp file, the program doesn't compile:
// test.cpp
#include "Settings.h"
error: C2079: 'dummy' uses undefined class 'User'
Possible solutions (which I do not like)
A solution is to include in User.h
in every cpp file that includes Settings.h
, i.e.:
// test.cpp
#include "User.h"
#include "Settings.h"
I do not prefer this solution, because I have to remember to include User.h
every time I include Settings.h
.
Another solution is to use the non-recommended DBO_EXTERN_TEMPLATES
macro, i.e.
// Settings.h
...
class Settings
{
public:
....
};
DBO_EXTERN_TEMPLATES(Settings)
I do not prefer this solution as this macro is not recommend, nor documented. DBO_EXTERN_TEMPLATES
doesn't work with all compilers.
Question
a. What is the best/preferred methodology to overcome circular dependencies between Wt::Dbo
objects avoiding the mentioned undefined class
error?
b. Why does solution 1. works?
I created a new (general - not Wt::Dbo
specific) question (with an MCVE), to clarify the specific situation: When are member functions of a templated class instantiated?
References
Wt::Dbo
tutorial: https://www.webtoolkit.eu/wt/doc/tutorial/dbo.html#_em_one_to_one_em_relations, but I want to place the different classes into different header files.Based on the answer of ChrisMM, another solution is to forward declare your class at the top of its header file:
Settings.h:
// include guard
class Settings;
#include "User.h"
class Settings { ... };
Users.h:
// include guard
class User;
#include "Settings.h"
class User { ... };
The advantage of this approach is that you only have to forward declare the class in its own header file and are allowed to just include the file in any other (header) file that need it.