Damian
Damian

Reputation: 5561

Is it possible in c++ to forbid calling a certain function at compile time?

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

Answers (4)

selbie
selbie

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

Matthieu M.
Matthieu M.

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

K-ballo
K-ballo

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

Mysticial
Mysticial

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

Related Questions