I remember looking around a few weeks ago for how to make a "static interface" in c++. Basically, I wanted a way to use the compiler to enforce that a class had certain static functions. Almost all of the internet resources I found basically said "Why would you ever want to do that; you don't really want to do that; you probably have bad design" and so on… continuously begging the question. Of course, they were right: the design was bad and that wasn't really what I wanted to do. Well, never the less, I still managed to think of a way to create a sort of static interface using a template class.
The strategy is to define a template class that uses the static methods of the template parameter class. That way, as long as the template is instantiated, the compiler will complain unless we have provided those static functions. We can ensure that the template is instantiated and enforce the inheritance idea by making the derived class extend from the template class we wrote to enforce those static methods.
Here is an example. We can create the static interface by declaring a class template that uses the functions we want to enforce as part of the interface.
template < typename T > class StaticInterface { public: StaticInterface() { int(*fooCheck)(int) = T::foo; bool(*barCheck)(bool) = T::bar; } };
By assigning T::foo
and T::bar
to function pointers, we are saying,
implicitly, that whatever class is provided as a parameter to this template
must have a static method called foo
and a static method called bar
and,
furthermore, that those static methods must have
the same signature as the function pointers we stuff them into.
By putting this code inside the constructor of the class, we know that this method of the template will be instantiated, even if we don't explicitly use it later in the code, as long as we derive from this class somewhere. So then, the last question is, where can we derive from it?
Well, in the class that we want to inherit the interface of course!
class DerivedClass : public StaticInterface { public: static int foo(int param){ return 10; } static bool bar(bool param){ return 20; } };
The DerivedClass
constructor implicitly calls the StaticInterface
constructor, which assigns the function pointers fooCheck
and barCheck
to
the address of the functions DerivedClass::foo
and DerivedClass::bar
. As a
result, if we forget the bar
function in the DerivedClass
the compiler
will choke with an error. g++ says the following:
src/poc/test/StaticInterfaceTest.cpp: In constructor `StaticInterface::StaticInterface() [with T = DerivedClass]': src/poc/test/StaticInterfaceTest.cpp:41: instantiated from here src/poc/test/StaticInterfaceTest.cpp:20: error: `bar' is not a member of `DerivedClass'
Pretty cool huh?
As a final note, please consider this "an interesting observation" and not necessarily a "great design choice". As I said, I decided against actually trying to utilize this idea in my project, and I urge you think carefully before about yours before trying to use it yourself.
Commentaires
Comments powered by Disqus