Sign in to follow this  
BaneTrapper

c++, Not being able to include more then 1 family class

Recommended Posts

Hello.

I am aware the title is a bit off but here is what i need.

 

class JSon1 {/*Unable to be included with JSon2*/};
class JSon2 {/*Unable to be included with JSon1*/};
class SSon1 {/*Unable to be included with SSon2*/};
class SSon2 {/*Unable to be included with SSon1*/};
 
class Base1 : public: JSon1, SSon1 {}; // valid
class Base2 : public: JSon1, JSon2 {}; // invalid
class Base3 : public: JSon1 {}; // valid
class Base4 : public: SSon1, SSon2 {}; // invalid

I will have classes of opposite functioning, so i want to protect the coder somehow so its not possible including the classes i want to mark as opposite.

 

Currently i know no way of doing this except trying to overload some operator witch i haven't think off yet.

Share this post


Link to post
Share on other sites
Off the top of my head, one way to do this is to have your mutually exclusive classes virtually inherit from a common base class. Give that base class a virtual function and have both your mutually exclusive classes implement that function. When a class tries to inherit from both of them, it won't know which to use so you'll get a compiler error. For example:
struct VirtualBase {
  virtual void if_you_get_an_error_involving_this_function_you_inherited_from_incompatible_bases(void) = 0;
  virtual ~VirtualBase() {}
};

struct A : virtual VirtualBase {
  void if_you_get_an_error_involving_this_function_you_inherited_from_incompatible_bases(void) {}
};

struct B : virtual VirtualBase {
  void if_you_get_an_error_involving_this_function_you_inherited_from_incompatible_bases(void) {}
};

struct C : A, B {}; // some sort of ambiguous inheritance error
This has a run time cost, so I would classify this as a cure worse than the disease.

Share this post


Link to post
Share on other sites

Off the top of my head, one way to do this is to have your mutually exclusive classes virtually inherit from a common base class. Give that base class a virtual function and have both your mutually exclusive classes implement that function. When a class tries to inherit from both of them, it won't know which to use so you'll get a compiler error. For example:

struct VirtualBase {
  virtual void if_you_get_an_error_involving_this_function_you_inherited_from_incompatible_bases(void) = 0;
  virtual ~VirtualBase() {}
};

struct A : virtual VirtualBase {
  void if_you_get_an_error_involving_this_function_you_inherited_from_incompatible_bases(void) {}
};

struct B : virtual VirtualBase {
  void if_you_get_an_error_involving_this_function_you_inherited_from_incompatible_bases(void) {}
};

struct C : A, B {}; // some sort of ambiguous inheritance error
This has a run time cost, so I would classify this as a cure worse than the disease.

 

 

You could use conditional compilation though and just use virtual inheritance for debug builds since its never actually used for anything other than catching incorrect usage of the classes.

Edited by SimonForsman

Share this post


Link to post
Share on other sites

I wouldn't use virtual inheritance in a debug build to force an error, it doesn't communicate the intention of the code at all.

 

What you need is conditional compilation. You can do it easily with include guards

 

in Json1.h

 

#ifndef JSON1_H_INCLUDED

#define JSON1_H_INCLUDED

 

#ifdef JSON2_H_INCLUDED

#error JSon2.h must not be included in files which include JSon1.h

#endif

 

#endif //JSON1_H_INCLUDED

 

In JSon2.h

 

#ifndef JSON2_H_INCLUDED

#define JSON2_H_INCLUDED

 

#ifdef JSON1_H_INCLUDED

#error JSon1.h must not be included in files which include JSon2.h

#endif

 

#endif //JSON2_H_INCLUDED

 

Clear, and gives an unambiguous error message.

Share this post


Link to post
Share on other sites

It also prevents a lot more than just inheritance. You could never use those two classes in the same header or same source file in any part of your code.

Share this post


Link to post
Share on other sites

There are circumstances where you could end up including the two files, without necessarily creating the kind of inheritance structure that BaneTrapper wants to avoid. An example might be a factory that instantiates one of the two implementations:

#include "client1.hpp"
#include "cient2.hpp"
 
std::shared_ptr<Client> make_client(Condition condition) {
    if(condition) {
         return std::make_shared<ClientOne>(/* ... */);
    }
    return std::make_shared<ClientTwo>(/* ... */);
}

 

 

However, if it is the case where the user is supposed to choose one of two implementations globally, then maybe such an approach makes sense.

Share this post


Link to post
Share on other sites

Its probably better to not protect the programmer, and just document for them that these configurations should be avoided. In fact, such "protection" is often a sign of lazy implementation on your part that just doesn't want to deal with certain cases -- this is one of the problems with the Singleton pattern, for instance. Nat saying that's necessarilty the case here, but be honest and ask yourself if it is, or if those things really are mutually exclusive.

 

Another way of providing protection would possibly be to only allow construction through a factory that only allows legitimate combinations to be created.

Share this post


Link to post
Share on other sites

Its probably better to not protect the programmer, and just document for them that these configurations should be avoided.

 

I have to disagree entirely. Your code and the interfaces to said code ought to designed in a way that prevents any potential misuse and mistakes by programmers that need to make use of them. Having to document gotchas because you didn't bother to design properly is a sign of lazy implementation on your part, not the other way around.

 

If there's something you don't want programmers to do with your code, do what you can to prevent it.

Edited by Indifferent

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this