Reputation: 5561
I have 2 classes:
class Entity {
void addChild(Entity* e);
};
class Control : public Entity {
};
What I want to do is to not allow adding a Control as a child of something that's not a Control. So, for example:
Control c;
Entity e;
e.addChild(c); // This line would throw an error (at compile time if possible);
The first thing I thought of is adding this to Entity:
void addChild(Control* c){
assert(false);
};
NOTE: both Entity and Control are abstract classes but both has many subclasses.
But is there any way to get an error at compile time?
Upvotes: 1
Views: 1245
Reputation: 104559
With a little bit of template specialization, it can be somewhat be done. But the only way I could make this work is by having the "addChild" method on the child element itself (renamed to "AttachToParent"). And passed by reference instead of by pointer. Template specialization is hard!
class Entity
{
public:
void AddChild(Entity* pChild);
};
class Control : public Entity
{
public:
template <typename T>
void AttachToParent(T& parent)
{
parent.You_are_trying_to_attach_Control_to_something_not_a_Control();
}
template <>
void AttachToParent<Control>(Control& parent)
{
parent.AddChild(this);
}
};
int main(int argc, char** argv)
{
Entity eParent;
Entity eChild;
Control cChild1;
Control cChild2;
eParent.AddChild(&eChild); // legal
cChild2.AttachToParent(cChild1); // allowed
//cChild1.AttachToParent(eParent); // uncomment this line and a compile error will occur
return 0;
}
Upvotes: 2
Reputation: 300019
In C++0x, the mechanism you seek is indeed possible.
class Entity {
public:
void addEntity(Entity*);
void addEntity(Control*) = delete;
};
But it does not work as you would expect it!
int main() {
Entity e;
Control c;
e.addEntity(&c); // ERROR
Entity& ec = c;
e.addEntity(&ec); // OK
}
As others have suggested, your use case is fishy. If you do not want Control
classes to be passed as Entity
, then remove the inheritance relationship. If you keep the inheritance relationship, then whenever an Entity
is expected, a Control
can be passed.
Upvotes: 2
Reputation: 81379
void addChild(Control c){ assert(false); };
But is there any way to get an error at compile time?
You could use static_assert
if your implementation has some C++11 support, or BOOST_STATIC_ASSERT
that will work in any implementation. However, I would suggest you redesign your hierarchy appropiately. Also note that you are mixing pointers and objects in the definitions of addChild
suggested.
Upvotes: 2
Reputation: 471369
You can declare the function, but don't implement it. That will give a linker error if you try to use it.
Upvotes: 6