7

After it turned out that what I originally wanted is probably not possible w/o involving C++11 I want to slightly change the requirement and ask you if this can be achieved.

previous question

Basically I want to check in compile time if a class is inheriting from "interface". By interface I mean class with pure virtual methods only. I would like to do the following code:

template <typename T>
class Impl : public T {
public:
STATIC_ASSERT_INTERFACE(T);
};

The behavior here is if T has only pure virtual methods then it will compile and if one of its methods is not then fail.

Can anyone think of something like that?

Community
  • 1
  • 1
Vadim S.
  • 187
  • 1
  • 4
  • 1
    Really all methods pure virtual? Even the destructor? – Andrzej Mar 28 '12 at 07:40
  • Presumably you'd want to check if `T` has base classes as well, and if so, whether they are "interfaces" too. But the answer is indeed "No". – MSalters Mar 28 '12 at 07:55

3 Answers3

2

This is basically similar to Java interfaces. In C++, there is no existence of interface as such, it's just a terminology used for a class with all pure-virtual methods and only static const data members.

Additionally, pure virtual methods may or may not have a function body. Thus C++ pure virtual methods are not exactly same as Java's abstract methods.

Unfortunately what you are asking is not possible to simulate in C++.

iammilind
  • 68,093
  • 33
  • 169
  • 336
  • Basically I want all the methods to be virtual to ensure I override them (I'm not talking about c'tor etc....). – Vadim S. Mar 28 '12 at 08:18
  • @VadimS.: do you mean you want to make sure you override all methods, or do you want to make sure that when you write a method which is supposed to override a base class method, it indeed does ? – Matthieu M. Mar 28 '12 at 08:44
  • I want to avoid (in compile time) a case that I want to override a method in the base class but the method is not defines as 'virtual'. – Vadim S. Mar 28 '12 at 09:07
1

First off, interfaces are not really a native concept to C++. I'm sure most programmers know what they are, but the compiler doesn't, and that's where you're running into problems. C++ can do a lot of things, and I bet you can twist it into looking like a lot of different languages, but if you're going to write C++, it's best to do things the C++ way.

Another thing - there's a lot of grey area here. What if you had an "interface" like you suggested, but somebody did one of these:

// Technically not a member function, but still changes the behavior of that class.
bool operator==(const Interface &left, const Interface &right);

I'm almost 100% sure you can't stop someone from doing that.

You may be able to make sure there are no member variables though, even though I'm not sure I agree with this way of doing things. Make an empty class, and then do a static_assert(sizeof(InterfaceClass) == sizeof(Empty)). I'm not sure if it's safe to assume the size would be 0 - that's a question for someone more familiar with the standards.

parkovski
  • 1,503
  • 10
  • 13
  • 1
    It won't ever be 0. Because if you declare multiple variables of type `Empty`, each of them has to have a unique address in the memory. – enobayram Mar 28 '12 at 08:14
  • 1
    `static_assert(sizeof(InterfaceClass) == sizeof(Empty))` - cannot be sure. Size of and empty class (with no member variables and no virtual functions) will be 1 byte and size of an `InterfaceClass` usually will not be 1 byte, most problably there would virtual function which will make the size 4 bytes (size of a pointer) – Sanish Mar 28 '12 at 08:26
1

What you want can not be done directly, as others have already explained.

However, you can still get the behavior you want with a bit of discipline from the interface developers. If all your interfaces derive from a common base class Interface, you can check that Interface is a base class at compile time using a technique similar to this question.

For example :

class Interface {
    public :
        virtual ~Interface() { }
};

template <typename T>
struct IsDerivedFromInterface {
    static T t();
    static char check(const Interface&);
    static char (&check(...))[2];
    enum { valid = (sizeof(check(t())) == 1) };
};

class MyInterface : public Interface {
    public :
        virtual void foo() = 0;
};

class MyBase {
    public :
        virtual void bar() { }
};

class Foo : public MyInterface {
    public :
        virtual void foo() { }
};
BOOST_STATIC_ASSERT(IsDerivedFromInterface<Foo>::valid);    // just fine

class Bar : public MyBase {
    public :
        virtual void bar() { }
};
BOOST_STATIC_ASSERT(IsDerivedFromInterface<Bar>::valid);    // oops

Of course, the developer of the base class can cheat and derive from Interface even though the base class is not an interface. Which is why I said it requires some discipline from the developer.

That said though, I can't see how this would be useful. I've never felt I needed this kind of compile time check.

Community
  • 1
  • 1
Sander De Dycker
  • 16,053
  • 1
  • 35
  • 40