I'm trying to create a sort of factory class in a template. I wanted to do something like a pure virtual function, but it needs to be static as I'm using the function to create types.
What I want to happen is when I declare a class, the template calls the static function. The static function is actually declared in the templatised class.
I've got as far as:
class Base
{
};
template<typename T>
class Type : public Base
{
public:
static void Create()
{
mBase = CreateBase();
}
private:
static Base* CreateBase();
static Base* mBase;
};
class MyType : public Type<MyType>
{
private:
static Base* CreateBase()
{
return new MyType;
}
};
template<typename T>
Base* Type<T>::mBase = NULL;
void test()
{
MyType::Create();
}
I get a link time error:
undefined reference to `Type<MyType>::CreateBase()
The CreateBase function is defined in the base type, so just call it:
template<typename T>
class Type : public Base
{
public:
static void Create()
{
mBase = Base::CreateBase();
}
//...
There is no need to declare another CreateBase in the template.
Found it.
The problem was I wasn't calling the derived class' function.
Here is the fix:
static void Create()
{
mBase = T::CreateBase();
}
Related
I have a templated SafeSingleton class, Base class which is derived from SafeSingleton and implements some base methods. I want to have class that is derived from Base and can be accessed via instance() method of SafeSingleton. The problem is that when I am trying to access Derived::instance() it returns the pointer to a Base class and the compiler doesn't know anything about methods of derived class. What should I do to make below code work.
template<class T>
class SingleTon {
public:
static T* instance()
{
return holder().instance;
}
protected:
template<class I>
struct Holder
{
Holder() : instance(new I())
{
}
I* instance;
};
static Holder<T> &holder()
{
static Holder<T> holder;
return holder;
}
};
// Hopefully issue is here, I am never creating SingleTon<Derived>, but how can it be done?
class Base : public SingleTon<Base> {
public:
Base() = default;
void printBase() {
std::cout << "Base";
}
};
class Derived : public Base {
public:
Derived() = default;
void printDerived() {
std::cout << "Derived";
}
};
int main()
{
Derived::instance()->printBase();
Derived::instance()->printDerived(); // Here is the error
//Error: main.cpp:57:26: error: ‘class Base’ has no member named ‘printDerived’
//57 | Derived::instance()->printDerived();
return 0;
}
template<class D>
class Base : public SingleTon<D> {
and
class Derived : public Base <Derived>
and ... done?
If you want to put Base's non-Ddependent methods in a cpp file, you'll have to get fancy. Have BaseImp that does not derive from SingleTon, put code there. Have Base<D> derive from it and write forwarding glue to it BaseImpl. But you probably don't need this.
I have a situation that I am attempting to write some c++ code to implement and I think I need to use templates but I am unsure. I don't think I understand templates well enough and just want to know if I am on the right track. I have never implemented a class that requires templates before.
I have a base class that needs to instantiate a new class and store it on a list for future access. The class that needs to be instantiated is derived from a base class that has one virtual method. After the class is instantiated, this method is called and the new instance is stored on a list. Another method is provided to get the instantiated object.
Say the virtual class is named foo:
class foo
{
public:
virtual void process() = 0;
}
the user would create a class bar:
class bar : public foo
{
public:
void process() {};
}
The class that I think needs to be a template class:
class Filter<Foo* T>
{
public:
// use value junk to derive foo
// and put the new instance on a std::list
add(Junk* junk);
T get();
private:
std::list<T> mFooList;
}
void Filter::add(Junk* junk)
{
T* foo = new T();
foo.p(junk);
mFooList.push_back(foo);
}
T* Filter::get()
{
if(!mFoolist.empty())
{
T* res = mFooList.back();
mFooList.pop_back();
return res;
}
return nullptr;
}
You don't need to use a templatevin this situation. In c++ a derived class can be assigned to a pointer of the base class. You can just use foo pointers.
class foo
{
public:
virtual void process();
};
class bar1: public foo
{
public:
void process();
};
class bar2 : public foo
{
public:
void process();
};
class filter
{
private:
std::list<foo*> _foos;
public:
foo* get();
void add(foo* f);
};
void filter::add(foo* f)
{
_foos.push_back(f);
}
foo* filter::get()
{
if(!_foos.empty())
{
return _foos.pop_back();
}
return nullptr;
}
You can then just add and get foos and bars
filter fil;
fil.add(new foo());
fill.add(new bar1());
fill.add(new bar2());
foo f = fill.get();
while(f != nullptr)
{
f->process();
delete f;
f = fil.get();
}
Here is what I am trying to achieve:
I have a list of Classes (Class1 to Classn) which inherit from a main Class
I would like to be able to instanciate an object of any of the n classes without having to do a large switch case (or equivalent). something along the lines of:
static ClassPointerType const * const ArrayOfClassTypes[]={ Class1, Class2, .. Classn };
static Class *GetObjectOfClass(int i)
{
return new ArrayOfClassTypes[i](some parameters for the constructor);
}
You can do that in other OO langues like Delphi where you have a TClass type and can get the class of an object... but I was not able to locate the equivalent functionality in C++.
Are you looking for something like this?
template<typename T>
std::unique_ptr<base> make()
{
return std::unique_ptr<base>(new T);
}
class factory
{
static constexpr std::unique_ptr<Base> (*fns[])(){make<derived_a>, make<derived_b>};
std::unique_ptr<base> get_object_of_class(int const i)
{
if (i < 0 || sizeof fns / sizeof *fns <= i) {
return nullptr;
}
return fns[i]();
}
};
You can add virtual method Clone to your base class and have it pure virtual (= NULL). Have there all required parameters.
Then you can override it in every subclass and create concrete classes there.
And in your factory do:
static ClassPointerType *GetObjectOfClass(int i)
{
return new ArrayOfClassTypes[i]->Clone(some params for the constructor);
}
And your array should contain concrete classes which you will clone:
static ClassPointerType* const ArrayOfClassTypes[]={ new ClassPointerType1(),new ClassPointerType2(), .. new ClassPointerTypeN() };
Complete example as requested:
// base class
class ClassPointerType
{
…
public:
virtual ClassPointerType* Clone(your params) = NULL;
};
// concrete classes
class ClassPointerType1 : public ClassPointerType
{
…
public:
// note: it clones own concrete instance
virtual ClassPointerType* Clone(your params) {return new ClassPointerType1(your params)};
}
class ClassPointerType2 : public ClassPointerType
{
…
public:
virtual ClassPointerType* Clone(your params) {return new ClassPointerType2(your params)};
}
…
class ClassPointerTypeN : public ClassPointerType
{
…
public:
virtual ClassPointerType* Clone(your params) {return new ClassPointerTypeN(your params)};
}
I implemented something alike recently. In my approach I stored a list of static create-functions instead and feeded a factory class with that
I implemented a templated base class wich
a) is able to register the derived into a factory class
b) implicitly forces the derived class to provide static functions.
However, you have to announce each derived class once. You can use it like this:
int main(int argc, char* argv[])
{
DerivedA::announce();
//and later
IInterface * prt = SingeltonFactory::create(DerivedA::_type);
delete prt;
return 0;
}
The Derived class DerivedA is defined as:
class DerivedA :
public IInterface,
public StaticBase<DerivedA>
{
public:
using StaticBase::announce;
static IInterface * create(){ return new DerivedA; }
static const std::string _type;
};
const std::string DerivedA::_type=std::string("DerivedA");
And the static Base class forcing the _type attribute and the create function to exist are defined as follows:
template<class TDerived>
class StaticBase
{
protected:
static void announce()
{
// register into factory:
SingeltonFactory::registerFun(TDerived::_type,TDerived::_create());
// The call of _type and _create implicitly forces the derived class to implement these, if it is deriving from this Base class
}
};
The factory class does contain a map of
std::map<std::string,tFunPtr>
where typedef tFunPtr is:
typedef IInterface * (*tFunPtr)(void);
This map you can use as an "array of classes" in order to handle it like an object. Thus, you represent the classes by a function pointer of the static create function
Does this answer your requirements? Shall I provide the factory class?
Assuming you are using a C++11 compiler here is a solution equivalent to the one provided earlier but less tricky and clever:
#include <iostream>
#include <memory>
#include <array>
class Base {
public:
virtual void doSomething() = 0;
};
class Der1: public Base {
private:
void doSomething() override {
std::cout << "Der1 did something" << std::endl;
}
};
class Der2: public Base {
private:
void doSomething() override {
std::cout << "Der2 did something" << std::endl;
}
};
template <typename T>
std::unique_ptr<Base> make() {
return std::unique_ptr<T>(new T);
}
int main() {
std::array<std::function<std::unique_ptr<Base>(void)>, 2> arr{make<Der1>,
make<Der2>};
auto obj = arr[0]();
obj->doSomething();
obj = arr[1]();
obj->doSomething();
}
You can use std::bind too to pass arguments to make if you have to use a non-default contructor
Hope that helps
No, in C++ classes are not first-order entities.
(I just noticed everybody is providing a solution to your problem but not precisely answering your question.)
I have a base class and a few derivative. I have to 'register' some static function from each of them. Here is the example:
class Base
{
// Some interface...
};
class Der1 : Base
{
static void Do();
};
class Der2 : Base
{
static void Do();
};
void processStatic()
{
SomeFunc(Der1::Do);
SomeFunc(Der2::Do);
}
As you see, SomeFunc receives function pointer. I want to do that automatically with each new derivative class, is it possible? Maybe, predefine static function in Base class and register it there. But I think it's impossible, yes?
Maybe, this will be more easier to understand what do I want:
class Der1 : Base
{
Der1() { SomeFunc(Der1::Do); }
static void Do();
};
class Der2 : Base
{
Der2() { SomeFunc(Der2::Do); }
static void Do();
};
EDIT: Completely replacing previous answer due to clarified requirements.
You could use the CRTP to declare a specialized base class that does nothing more than call your registration function:
#include <iostream>
void SomeFunc(void(*fp)()) {
(*fp)();
};
template <class D>
struct ExtraBass {
ExtraBass() {
static bool once;
if(!once)
SomeFunc(D::Do);
once = true;
}
};
struct Bass {
};
struct Drive : Bass, ExtraBass<Drive> {
static void Do() { std::cout << "Drive::Do\n"; }
};
struct Deride : Bass , ExtraBass<Deride> {
static void Do() { std::cout << "Deride::Do\n"; }
};
int main() {
Drive d1;
Deride d2;
Deride d3;
}
This is not an easy thing to do in C++, but I'm not saying it's impossible. If all you need is a list of subclass names, these answers might help:
Somehow register my classes in a list
c++ List of classes without initializing them for use of static functions
Seems either macro magic or boost mpl is your tool of choice.
I just wondering, if you did something like
void SomeFunc(void (*doFunc)())
{
doFunc();
}
template <class T> int Register()
{
SomeFunc(T::Do);
return 0;
}
template <class T> class Base
{
static int _i;
};
template <class T> int Base<T>::_i = Register<T>();
class Derived : Base<Derived>
{
public:
static void Do() { }
};
With c++, Is there a way to get a derived class to inherit its own static initializer? I am trying to do something like the following:
class Base {
public:
class StaticInit {
public:
virtual StaticInit() =0;
};
};
class Derived: public Base {
public:
virtual StaticInit::StaticInit() {
//do something with the derived class
}
static StaticInit init;
}
static Derived::StaticInit init;
it would also be nice if I didn't have to define the init var in each derived class. I am currently redefining the StaticInit internal class in each derived class but it seems redundant.
Each derived class is a singleton, and I need the instance to be stored in a lookup table at program startup.
I use templates to do this, rather than inheritance - something like:
template <typename T>
struct StaticInit {
StaticInit() {
// do whatever with T
}
};
in use:
static StaticInit <SomeClass> init;
Use the CRTP:
template <class D>
class Base {
public:
class StaticInit {
public:
StaticInit() { D::initStatic(*this); }
};
static StaticInit init;
};
template <class D>
Base<D>::StaticInit init;
class Derived: public Base<Derived> {
public:
initStatic(Base<Derived>::StaticInit& s) {
// Do derived-specific initialisation on s.
}
}