C++ templates: Accessing template variables - c++

I am new to C++ world.
I am trying to implement code using templates.
template<class PageType>
class Book
{
//implementation
public:
PageType* FreeQ; //holds the pointers to pages which are yet to be written
PageType* BusyQ; //holds the pointers to pages which are being written
PageType* DoneQ; //holds the pointers to pages which were written
getPagetoWrite(); //Get from FreeQ and put in BusyQ
setPageAsFree(); //Erase data and put in FreeQ
}
//example for PageType implementation
class PlasticType
{
mutex; // must
status; // must
*prev; // must
*next; // must
Write( );
Read();
}
I want to know whether there is any way to inform the compiler that implementation of PageType must contain specific variables which will be used in class Book implementation (in getPagetoWrite and setPageAsFree) without creating the instance of the type PageType.
Hope i made myself clear.

I dont think that it is possible to enforce that PageType contain specific variables, this is done simple at compile time during template instantiation - and you really dont need anything else. You can use C++11 std::is_base_of to enforce with static_assert that your PageType implements some base class to which you could put getPagetoWrite and setPageAsFree, but still you will have to instantiate your templates - which is OK.
#include <type_traits>
class Base {
};
class X : public Base {
};
class Z {
};
template <typename T>
class Foo {
static_assert(std::is_base_of<Base,T>::value,"must be derived from Base");
public:
Foo() {
}
};
int main(int argc, char** argv) {
Foo<Z> foo_z_type; // gives compile error: static assertion failed: must be derived from Base
Foo<X> foo_z_type; // OK
return 0;
}
http://coliru.stacked-crooked.com/a/bf91079681af3b0e

As far as i know, you can just use the variables' or functions' names that should be there in your code. Like this:
void getPagetoWrite()
{
...
//PageType should have a member called pagenum for which operator++ makes sense
BusyQ->pagenum++;
...
}
If then you instantiate your Book template with some class which doesn't have a pagenum member, you will get a compile time error.

Related

Initialize object from unknown derived class of known base class

So, I'm making a library for a little D2D Engine; but that's not the point, the thing is, I have this class which will be the base class the user's class will inherit. My main idea would be something like this:
struct BaseEngine {
// I have two pure virtual functions so the user has to define them.
virtual bool onLoad() = 0;
virtual bool onFrame() = 0;
};
Now, if it all were to be in the same project, I could do something like this right after that:
struct Derived : public BaseEngine {
bool onLoad() override;
bool onFrame() override;
};
const std::unique_ptr<BaseEngine> app = std::make_unique<Derived>();
But my idea is, in fact, to not hold the derived class in my header files, and build the library without any possible definition of a derived class, thus, the user can just name it whatever they want in their project.
Of course it won't let me compile it, because I can't construct BaseEngine because it has pure virtual functions.
Then I though of somehow using templates to maybe solve this issue? Now I'm not very familiar with templates, but my idea was to make something like:
std::unique_ptr<BaseEngine> app;
template<class T : public BaseEngine>
void instantiator() {
app = std::make_unique<T>();
}
Knowing that T holds an implementation for onLoad() and onFrame().
But of course, when I need a feature such as templates of explicitly derived classes, no feature exists (not that I know of, at least).
My main question being: is there a way for me to initialize an object from an "unknown" derived class of my known base class?
Edit: forgot to mention that the main function (WinMain in this case) will be on the engine side, as it takes care of window class registration and all those nasty messages.
It sounds like you'd like to compile your code as a shared library, that you can link to in another project that will become the main executable. Unfortunately, there can be issues sharing class types between libraries and executables due to differences in how they might be compiled--I wouldn't recommend going down that route.
If you can compile it all at once, though (i.e. the user has access to uncompiled source and header files) you won't have to deal with that. Just provide a function that takes an instance of BaseEngine.
// BaseEngine.h
class BaseEngine { /* ... */ }
void startGame(std::unique_ptr<BaseEngine> engine) { /* ... */ }
// main.cpp (user edits this file)
#include "BaseEngine.h"
class DerivedEngine : public BaseEngine {
// override methods here
}
int main() {
return startGame(std::make_unique<DerivedEngine>());
}
The usual answer to this would be to have a function in your engine that takes a caller-created BaseEngine derived object as an argument.
// Engine side function
bool InitializeEngine(BaseEngine * pEngine);
An alternative answer (depending on how the user-supplied code is bundled) would be to have an exported function with a set name and have that function return a created BaseEngine derived object.
// User side code
BaseEngine * CreateEngine();
And then use dlopen/dlsym (or LoadLibrary/GetProcAddress on windows) to obtain the function pointer for CreateEngine. In either case it is the user's code where the object type is known that is responsible for creating the object.
Static polymorphism: the Curiously Recurring Template Pattern (CRTP)
You may want to consider using the Curiously Recurring Template Pattern (CRTP):
#include <ios>
#include <iostream>
#include <memory>
#include <type_traits>
template <class T> struct BaseEngine {
bool onLoad() const { return static_cast<T const *>(this)->onLoad(); }
bool onFrame() { return static_cast<T *>(this)->onLoad(); }
};
// API exposed to library users.
template <typename T,
typename = std::enable_if_t<std::is_base_of<BaseEngine<T>, T>::value>>
auto createEngine() {
return std::make_unique<T>();
}
template <typename T> bool foo(const BaseEngine<T> &engine) {
return engine.onLoad();
}
// Stub for your own testing etc.
struct StubEngine : BaseEngine<StubEngine> {
bool onLoad() const {
std::cout << "stub onLoad()\n";
return true;
}
bool onFrame() {
std::cout << "stub onFrame()\n";
return false;
}
};
struct BadEngine {};
int main() {
auto engine = createEngine<StubEngine>();
// auto bad_engine = createEngine<BadEngine>();
// error: no matching function for call to 'createEngine'
const bool f = foo(*engine); // stub onLoad()
std::cout << std::boolalpha << f; // true
return 0;
}
By implementing static polymorphism using templates, you can work within you lib with a type template parameter T in the context of BaseEngine without having to know what T is (as it will be up to the library user to implement particular concrete "statically derived" classes, i.e., specific T's); possibly placing, however, restrictions on T using type traits and SFINAE.

How to self-document a callback function that is called by template library class?

I have a function User::func()(callback) that would be called by a template class (Library<T>).
In the first iteration of development, everyone know that func() serves only for that single purpose.
A few months later, most members forget what func() is for.
After some heavy refactoring, the func() is sometimes deleted by some coders.
At first, I didn't think this is a problem at all.
However, after I re-encountered this pattern several times, I think I need some counter-measure.
Question
How to document it elegantly? (cute && concise && no additional CPU cost)
Example
Here is a simplified code:-
(The real world problem is scattering around 10+ library-files & 20+ user files & 40+ functions.)
Library.h
template<class T> class Library{
public: T* node=nullptr;
public: void utility(){
node->func(); //#1
}
};
User.h
class User{
public: void func(){/** some code*/} //#1
//... a lot of other functions ...
// some of them are also callback of other libraries
};
main.cpp
int main(){
Library<User> li; .... ; li.utility();
}
My poor solutions
1. Comment / doc
As the first workaround, I tend to add a comment like this:-
class User{
/** This function is for "Library" callback */
public: void func(){/** some code*/}
};
But it gets dirty pretty fast - I have to add it to every "func" in every class.
2. Rename the "func()"
In real case, I tend to prefix function name like this:-
class User{
public: void LIBRARY_func(){/** some code*/}
};
It is very noticeable, but the function name is now very longer.
(especially when Library-class has longer class name)
3. Virtual class with "func()=0"
I am considering to create an abstract class as interface for the callback.
class LibraryCallback{
public: virtual void func()=0;
};
class User : public LibraryCallback{
public: virtual void func(){/** some code*/}
};
It provides feeling that func() is for something-quite-external. :)
However, I have to sacrifice virtual-calling cost (v-table).
In performance-critical cases, I can't afford it.
4. Static function
(idea from Daniel Jour in comment, thank!)
Almost 1 month later, here is how I use :-
Library.h
template<class T> class Library{
public: T* node=nullptr;
public: void utility(){
T::func(node); //#1
}
};
User.h
class User{
public: static void func(Callback*){/** some code*/}
};
main.cpp
int main(){
Library<User> li;
}
It is probably cleaner, but still lack self-document.
func is not a feature of User. It is a feature of the User-Library<T> coupling.
Placing it in User if it doesn't have clear semantics outside of Library<T> use is a bad idea. If it does have clear semantics, it should say what it does, and deleting it should be an obviously bad idea.
Placing it in Library<T> cannot work, because its behavior is a function of the T in Library<T>.
The answer is to place it in neither spot.
template<class T> struct tag_t{ using type=T; constexpr tag_t(){} };
template<class T> constexpr tag_t<T> tag{};
Now in Library.h:
struct ForLibrary;
template<class T> class Library{
public: T* node=nullptr;
public: void utility(){
func( tag<ForLibrary>, node ); // #1
}
};
in User.h:
struct ForLibrary;
class User{
/** This function is for "Library" callback */
public:
friend void func( tag_t<ForLibrary>, User* self ) {
// code
}
};
or just put this into the same namespace as User, or the same namespace as ForLibrary:
friend func( tag_t<ForLibrary>, User* self );
Before deleting func, you'll track down ForLibrary.
It is no longer part of the "public interface" of User, so doesn't clutter it up. It is either a friend (a helper), or a free function in the same namespace of either User or Library.
You can implement it where you need a Library<User> instead of in User.h or Library.h, especially if it just uses public interfaces of User.
The techniques used here are "tag dispatching", "argument dependent lookup", "friend functions" and preferring free functions over methods.
From the user side, I would use crtp to create a callback interface, and force Users to use it. For example:
template <typename T>
struct ICallbacks
{
void foo()
{
static_cast<T*>(this)->foo();
}
};
Users should inherit from this interface and implement foo() callback
struct User : public ICallbacks<User>
{
void foo() {std::cout << "User call back" << std::endl;}
};
The nice thing about it is that if Library is using ICallback interface and User forget to implement foo() you will get a nice compiler error message.
Note that there is no virtual function, so no performance penalty here.
From the library side, I would only call those callbacks via its interfaces (in this case ICallback). Following OP in using pointers, I would do something like this:
template <typename T>
struct Library
{
ICallbacks<T> *node = 0;
void utility()
{
assert(node != nullptr);
node->foo();
}
};
Note that things get auto documented in this way. It is very explicit that you are using a callback interface, and node is the object who has those functions.
Bellow a complete working example:
#include <iostream>
#include <cassert>
template <typename T>
struct ICallbacks
{
void foo()
{
static_cast<T*>(this)->foo();
}
};
struct User : public ICallbacks<User>
{
void foo() {std::cout << "User call back" << std::endl;}
};
template <typename T>
struct Library
{
ICallbacks<T> *node = 0;
void utility()
{
assert(node != nullptr);
node->foo();
}
};
int main()
{
User user;
Library<User> l;
l.node = &user;
l.utility();
}
Test.h
#ifndef TEST_H
#define TEST_H
// User Class Prototype Declarations
class User;
// Templated Wrapper Class To Contain Callback Functions
// User Will Inherit From This Using Their Own Class As This
// Class's Template Parameter
template <class T>
class Wrapper {
public:
// Function Template For Callback Methods.
template<class U>
auto Callback(...) {};
};
// Templated Library Class Defaulted To User With The Utility Function
// That Provides The Invoking Of The Call Back Method
template<class T = User>
class Library {
public:
T* node = nullptr;
void utility() {
T::Callback(node);
}
};
// User Class Inherited From Wrapper Class Using Itself As Wrapper's Template Parameter.
// Call Back Method In User Is A Static Method And Takes A class Wrapper* Declaration As
// Its Parameter
class User : public Wrapper<User> {
public:
static void Callback( class Wrapper* ) { std::cout << "Callback was called.\n"; }
};
#endif // TEST_H
main.cpp
#include "Test.h"
int main() {
Library<User> l;
l.utility();
return 0;
}
Output
Callback was called.
I was able to compile, build and run this without error in VS2017 CE on Windows 7 - 64bit Intel Core 2 Quad Extreme.
Any Thoughts?
I would recommend to name the wrapper class appropriately, then for each specific call back function that has a unique purpose name them accordingly within the wrapper class.
Edit
After playing around with this "template magic" well there is no such thing...
I had commented out the function template in the Wrapper class and found that it is not needed. Then I commented out the class Wrapper* that is the argument list for the Callback() in User. This gave me a compiler error that stated that User::Callback() does not take 0 arguments. So I looked back at Wrapper since User inherits from it. Well at this point Wrapper is an empty class template.
This lead me to look at Library. Library has a pointer to User as a public member and a utility() function that invokes User's static Callback method. It is here that the invoking method is taking a pointer to a User object as its parameter. So it lead me to try this:
class User; // Prototype
class A{}; // Empty Class
template<class T = User>
class Library {
public:
T* node = nullptr;
void utility() {
T::Callback(node);
}
};
class User : public A {
public:
static void Callback( A* ) { std::cout << "Callback was called.\n"; }
};
And this compiles and builds correctly as the simplified version. However; when I thought about it; the template version is better because it is deduced at compile time and not run time. So when we go back to using templates javaLover had asked me what class Wrapper* means or is within the argument list for the Callback method within the User class.
I'll try to explain this as clearly as I can but first the wrapper Class is just an empty template shell that User will inherit from and it does nothing but act as a base class and it now looks like this:
template<class T>
class Wrapper { // Could Be Changed To A More Suitable Name Such As Shell or BaseShell
};
When we look at the User class:
class User : public Wrapper<User> {
public:
static void Callback( class Wrapper* ) { // print statement }
};
We see that User is a non-template class that inherits from a template class but uses itself as the template's argument. It contains a public static method
and this method doesn't return any thing but it does take a single parameter; this is also evident in the Library class that has its template parameter as a User class. When the Library's utility() method invokes User's Callback() method the parameter that the Library is expecting is a pointer to a User object. So when we go back to the User class instead of declaring it as a User* pointer directly in its declaration I'm using the empty class template that it inherits from. However if you try to do this:
class User : public Wrapper<User> {
public:
static void Callback( Wrapper* ) { // print statement }
};
You should get a message that Wrapper* is missing it's argument list. We could just do Wrapper<User>* here but that is redundant since we already see that User is inheriting from Wrapper that takes itself. So we can fix this and make it cleaner just by prefixing the Wrapper* with the class keyword since it is a class template. Hence the template magic... well there is no magic here... just compiler intrinsic and optimizations.
While I know that I don't answer your specific question (how to document the not-to-be-deleted function) I would solve your problem (keeping the seemingly unused callback function in the code base) by instantiating Library<User> and calling the utility() function in a unit test (or maybe it should rather be called an API test...). This solution would probably scale to your real world example too, as long as you don't have to check each possible combination of library classes and callback functions.
If you are lucky enough to work in an organization where successful unit tests and code review are required before changes go into the code base this would require a change to the unit tests before anyone could remove the User::func() function and such a change would probably catch the attention of a reviewer.
Then again, you know your environment and I don't, and I'm aware that this solution doesn't fit all situations.
Here is a solution using a Traits class:
// Library.h:
template<class T> struct LibraryTraits; // must be implemented for every User-class
template<class T> class Library {
public:
T* node=nullptr;
void utility() {
LibraryTraits<T>::func(node);
}
};
// User.h:
class User { };
// must only be implemented if User is to be used by Library (and can be implemented somewhere else)
template<> struct LibraryTraits<User> {
static void func(User* node) { std::cout << "LibraryTraits<User>::func(" << node << ")\n"; }
};
// main.cpp:
int main() {
Library<User> li; li.utility();
}
Advantages:
It is obvious by the naming that LibraryTraits<User> is only required for interfacing User by Library (and can be removed, once either Library or User gets removed.
LibraryTraits can be specialized independent of Library and User
Disadvantages:
No easy access to private members of User (making LibraryTraits a friend of User would remove the independence).
If the same func is needed for different Library classes multiple Trait classes need to be implemented (could be solved by default implementations inheriting from other Trait classes).
This heavily reminds an old good Policy-Based Design, except in your case you do not inherit the Library class from the User class.
Good names are the best friends of any API. Combine this and the well-known patter of Policy-Based Design (well-known is very important because the class names with the word Policy in it will immediately ring the bell in many readers of the code) and, I assume, you get a well self-documenting code.
Inheritance won't give you any performance overhead, but will give you an ability to have the Callback as a protected method, that will give some hint that it is supposed to be inherited and be used somewhere.
Have clearly standing-out and consistent naming among multiple User-like classes (e.g. SomePolicyOfSomething in the manner of aforementioned Policy-Based Design), as well as, the template arguments for the Library (e.g SomePolicy, or I would call it TSomePolicy).
Having using declaration of the Callback in the Library class might give much clearer and earlier errors (e.g. from IDE, or modern clang, visial studio syntax parsers for IDE).
Another arguable option might be a static_assert if you have C++>=11. But in this case it must be used in every User-like class ((.
Not a direct answer to your question on how to document it, but something to consider:
If your Library template requires an implementation of someFunction() for each class to be used in it, i'd recommend adding it as a template argument.
#include <functional>
template<class Type, std::function<void(Type*)> callback>
class Library {
// Some Stuff...
Type* node = nullptr;
public:
void utility() {
callback(this->node);
}
};
Might make it even more explicit, so that other devs know it's needed.
abstract class is the best way to enforce the function not to be deleted. So i recommend implementing the base class with pure virtual function, so that derived has to define the function.
OR second solution would be to have function pointers so that performance will be saved by avoiding extra overhead of V-table creation and calling.
If it is not obvious that func() is needed in User, then I'd argue you're violating the single responsibility principle. Instead create an adapter class of which User as a member.
class UserCallback {
public:
void func();
private:
User m_user;
}
That way the existance of UserCallback documents that func() is an external call back, and separates out Library's need of a callback from the actual responsibilities of User.

Add subclasses of templated base-class to container without super-base-class?

I'm trying to create a vector (or any STL container, really) that could hold a set of various objects that are subclasses of one specific type. The problem is that my base class is templated.
From what I can tell, I have to create an interface/abstract super base class (not sure what the preferred C++ terminology is). I'd prefer not to do this, and just use my (templated) abstract base class. Below is some example code.
Basically, is there a way not to require the WidgetInterface? Someway to tell the compiler to ignore template requirements? If I must have WidgetInterface, am I going the right way with the following?
#include <vector>
#include "stdio.h"
enum SomeEnum{
LOW = 0,
HIGH = 112358
};
// Would like to remove this WidgetInterface
class WidgetInterface{
public:
// have to define this so we can call it while iterating
// (would remove from Widget if ended up using this SuperWidget
// non-template baseclass method)
virtual void method() = 0;
};
template <class TDataType>
class AbstractWidget : public WidgetInterface{
public:
TDataType mData;
virtual void method() = 0;
// ... bunch of helper methods etc
};
class EnumWidget : public AbstractWidget<SomeEnum>{
public:
EnumWidget(){
mData = HIGH;
}
void method(){
printf("%d\n", mData); // sprintf for simplicity
}
};
class IntWidget : public AbstractWidget<int>{
public:
IntWidget(){
mData = -1;
}
void method(){
printf("%d\n", mData); // sprintf for simplicity
}
};
int main(){
// this compiles but isn't a workable solution, not generic enough
std::vector< AbstractWidget<int>* > widgets1;
// only way to do store abitary subclasses?
std::vector<WidgetInterface*> widgets2;
widgets2.push_back(new EnumWidget());
widgets2.push_back(new IntWidget());
for(std::vector<WidgetInterface*>::iterator iter = widgets2.begin();
iter != widgets2.end(); iter++){
(*iter)->method();
}
// This is what i'd _like_ to do, without needing WidgetInterface
// std::vector< AbstractWidget* > widgets3;
return 0;
}
No, you can't use directly AbstractWidget as a parameter of STL container or anything else.
The reason is that class AbstractWidget does not exist. It is only a template for compiler to construct classes from.
What exists is AbstractWidget<SomeEnum> and AbstractWidget<int> only because of EnumWidget and IntWidget inheriting from them.
Templates exist at compiler-level only. If AbstractWidget<T> weren't used anywhere in your code, there would be no traces of it during the runtime.
Therefore, the code you posted seems to be the best (if not only) solution for your problem.
What you've done is the solution: you need a common class/interface, and since AbstractWidget is class template, therefore it cannot be used as common class for all concrete classes for which the template argument is different. So I think, you should go with this class design. It seems to be quite reasonable solution.
In fact the classes AbstractWidget<int> and AbstractWidget<double> are different classes, so your class IntWidget is a subclass of the first but is in no relation with the second. You need to have a common parent class to put in the vector so unfortunately you can not avoid the common interface that is not templated.
This could be completely in the wrong direction, but could you do something like this:
template <class T>
class ConcreteWidget : public AbstractWidget<T>
{
};
and then use template specialization to define your specific widgets like this:
template <>
class ConcreteWidget : public AbstractWidget<int>
{
public:
ConcreteWidget() : mData(-1) {}
};
template <>
class ConcreteWidget : public AbstractWidget<SomeEnum>
{
public:
ConcreteWidget() : mData(HIGH) {}
};
So rather than having an IntWidget and an EnumWidget, you'd have a ConcreteWidget and ConcreteWidget and then could simply have a vector<WidgetInterface> that would be the super of all of these generic children?
I'm not sure if this solves your problem, or would even work. I'd love feedback on this answer.

C++: Can I write a template class that derives from T?

I'm not exactly sure how to word this in English, but I want to do something like this:
template <class T>
class derived: public T
{ blah };
Where basically, I have a template class, but I'm deriving a new class from the class that is specified in the template? I.e. so I wouldn't necessarily know the class at compile time.
Is this even possible? If so, What are the semantics for this?
For example, say I'm trying to write a "parent" class. For the purposes of this example, let's say it's a tree parent. The tree parent, is a tree itself (so it inherits from tree), but also has a vector of references to child trees.However, the parent class itself doesn't have to be a tree; it could be any class, such that I could write something like:
Parent<tree> treeParent;
Parent<shrub> shrubParent;
Yes. That is possible. Try doing that.
I wouldn't necessarily know the class at compile time.
I think, you mean "I wouldn't necessarily know the class at the time of defining the class template."
By the time you compile, you've already defined the class template, and used it in your code, passing template argument to it, which means you know the class (i.e template argument) at compile time. If you don't know the class to be used as base, then you cannot even compile the code.
This is indeed possible and commonly used for policy based design:
Like in this incredibly contrived example:
template<typename OutputPolicy>
struct Writer : public OutputPolicy {
using OutputPolicy::print;
void write(const std::string&) {
//do some formatting etc.
print(string);
}
};
class StdoutPolicy {
public:
set_linebreaks(const std::string&);
protected:
void print(const std::string&);
};
The public method in the policy will be accessible through Writer. That way a policy can decorate the class it is used in with additional methods.
Yes this is possible. The semantic for this is no different from the semantic for any other use of a template parameter in the class template. You can have a member of type T, a function parameter of type T, and you can have T as a base class too. It's not special.
Like this:
#include <iostream>
using namespace std;
template<typename T>class classTemplateBase
{
public:
T value;
classTemplateBase(T i)
{
this->value = i;
}
void test()
{
cout << value << endl;
}
};
class classTemplateChild : public classTemplateBase<char>
{
public:
classTemplateChild( ): classTemplateBase<char>( 0 ) // default char is NUL
{
;
}
classTemplateChild(char c): classTemplateBase<char>( c )
{
;
}
void test2()
{
test();
}
};
int main()
{
classTemplateBase <int> a( 42 );
classTemplateChild b( 'A' );
a.test(); // should print "42"
b.test(); // should print "A"
b.test2(); // should print "A"
return 0;
}
This is possible an it is also very common and has gotten it's own name: the Curiously recurring template pattern. See the Wikipeida entry on Curiously recurring template pattern.

Enforce static method overloading in child class in C++

I have something like this:
class Base
{
public:
static int Lolz()
{
return 0;
}
};
class Child : public Base
{
public:
int nothing;
};
template <typename T>
int Produce()
{
return T::Lolz();
}
and
Produce<Base>();
Produce<Child>();
both return 0, which is of course correct, but unwanted. Is there anyway to enforce the explicit declaration of the Lolz() method in the second class, or maybe throwing an compile-time error when using Produce<Child>()?
Or is it bad OO design and I should do something completely different?
EDIT:
What I am basically trying to do, is to make something like this work:
Manager manager;
manager.RegisterProducer(&Woot::Produce, "Woot");
manager.RegisterProducer(&Goop::Produce, "Goop");
Object obj = manager.Produce("Woot");
or, more generally, an external abstract factory that doesn't know the types of objects it is producing, so that new types can be added without writing more code.
There are two ways to avoid it. Actually, it depends on what you want to say.
(1) Making Produce() as an interface of Base class.
template <typename T>
int Produce()
{
return T::Lolz();
}
class Base
{
friend int Produce<Base>();
protected:
static int Lolz()
{
return 0;
}
};
class Child : public Base
{
public:
int nothing;
};
int main(void)
{
Produce<Base>(); // Ok.
Produce<Child>(); // error :'Base::Lolz' : cannot access protected member declared in class 'Base'
}
(2) Using template specialization.
template <typename T>
int Produce()
{
return T::Lolz();
}
class Base
{
public:
static int Lolz()
{
return 0;
}
};
class Child : public Base
{
public:
int nothing;
};
template<>
int Produce<Child>()
{
throw std::bad_exception("oops!");
return 0;
}
int main(void)
{
Produce<Base>(); // Ok.
Produce<Child>(); // it will throw an exception!
}
There is no way to override a static method in a subclass, you can only hide it. Nor is there anything analogous to an abstract method that would force a subclass to provide a definition. If you really need different behaviour in different subclasses, then you should make Lolz() an instance method and override it as normal.
I suspect that you are treading close to a design problem here. One of the principals of object-oriented design is the substitution principal. It basically says that if B is a subclass of A, then it must be valid to use a B wherever you could use an A.
C++ doesn't support virtual static functions. Think about what the vtable would have to look like to support that and you'll realize its a no-go.
or maybe throwing a compile-time error when using Produce<Child>()
The modern-day solution for this is to use delete:
class Child : public Base
{
public:
int nothing;
static int Lolz() = delete;
};
It helps avoid a lot of boilerplate and express your intentions clearly.
As far as I understand your question, you want to disable static method from the parent class. You can do something like this in the derived class:
class Child : public Base
{
public:
int nothing;
private:
using Base::Lolz;
};
Now Child::Lolz becomes private.
But, of course, it's much better to fix the design :)