I have the following piece of code. I have abstracted out and my class looks something like this:
#include<iostream>
#include<map>
using namespace std;
template <class K>
class Base {
private:
static std::map<std::string, Base*> derived_map;
//other private data
public:
Base(std::string modName) {
if (derived_map.find(modName) == derived_map.end())
{
derived_map.insert(make_pair(modName, this));
}
}
};
template <class K> std::map<std::string, Base<K>*> Base<K>::derived_map;
class Derived: public Base<Derived>
{
public:
Derived(std::string modname): Base<Derived>(modname)
{
}
};
Derived obj("derived1"); // <<< This casuses segfault
int main()
{
}
When I declare the Derived obj globally, it segfaults. When I declared the Derived obj inside of my main then it doesn't. I am not able to figure out what I might be doing wrong. I am trying to maintain a list of derived class pointers in my base class using a std::map. Any clues ?
You have 2 global variables with dependencies:
obj requires that Base<Derived>::derived_map is initialized correctly.
global initialization across translation unit is done in undefined order.
You may solve your code with something like:
template <class K>
class Base {
private:
static std::map<std::string, Base*>& get_derived_map()
{
static std::map<std::string, Base*> derived_map; // initialized the first time
// get_derived_map is called
return derived_map;
}
//other private data
public:
explicit Base(const std::string& modName) {
get_derived_map().insert(make_pair(modName, this));
}
};
Related
I have a sprite class, which has a templatised data member. It holds an object, which has a pointer to this specialised sprite template class.
That object requires a forward declaration of my sprite class, but since sprite is a template class, I need to include the full header. Therefore I get a cyclic dependancy which I am unable to figure out
Sprite.h
#include "myclass.h"
template<typename SpriteType, typename = typename std::enable_if_t<std::is_base_of_v<sf::Transformable, SpriteType> && std::is_base_of_v<sf::Drawable, SpriteType>>>
class Sprite {
public:
SpriteType s;
myclass<SpriteType>;
Sprite() {
}
auto foo() {
return s;
}
private:
};
myclass.h
#include "Sprite.h"
//a sprite of type T, is going to create a myclass<Sprite<T>>, a pointer of the Sprite<T> is held in myclass.
template<typename T>
class myclass
{
public:
std::shared_ptr<Sprite<T>> ptr;
myclass() {
}
private:
};
How could I solve this cyclic dependency?
So in summary:
-Sprite is a template class.
-Sprite holds an object to another class. This other class holds a pointer to my this templated sprite class.
-This gives me a cyclic dependency, since both classes are now templates, and need to have their implementations written in their header files.
Simplified decoupling, based on #Taekahns solution.
template<typename T>
class myclass
{
public:
std::shared_ptr<T> ptr;
myclass() {
}
private:
};
template<typename SpriteType, typename = typename std::enable_if_t<std::is_base_of_v<sf::Transformable, SpriteType> && std::is_base_of_v<sf::Drawable, SpriteType>>>
class Sprite {
public:
SpriteType s;
// DO NOT PASS SpriteType here, put the whole Sprite<SpriteType>
myclass<Sprite<SpriteType>> t;
Sprite() {
}
auto foo() {
return s;
}
private:
};
One of the great thing about templates is breaking type dependencies.
You could do something like this. Simplified for readability.
template<typename T>
class myclass
{
public:
std::shared_ptr<T> ptr;
myclass() {
}
private:
};
template<typename SpriteType, typename = std::enable_if_t<std::is_base_of_v<base_class, SpriteType>>>
class Sprite {
public:
SpriteType s;
myclass<Sprite<SpriteType>> t;
Sprite() {
}
auto foo() {
return s;
}
private:
};
That is one of many options.
Another option is to use an interface. i.e. a pure virtual base class that isn't a template.
Example:
I think something like this should do it. Starting to get a hard to follow though.
class base_sprite
{
public:
virtual ~base_sprite(){};
virtual int foo() = 0;
};
template<typename T>
class myclass
{
public:
std::shared_ptr<base_sprite> ptr;
myclass() : ptr(std::make_shared<T>())
{
};
};
template<typename SpriteType>
class Sprite : public base_sprite{
public:
myclass<Sprite<SpriteType>> l;
int foo() override {return 0;};
};
Assume I have a class, which stores references to the derived class member variables via a proxy class in a map. This map is populated in a function called let say foo(). It could look something like this:
#include <map>
#include <memory>
class property_base
{
};
template<typename T>
class property : public property_base
{
public:
property(T& property) : property_(property)
{
}
private:
T& property_;
};
template<typename T>
class base
{
public:
base()
{
static_cast<T*>(this)->foo();
}
protected:
std::map<std::string, std::unique_ptr<property_base>> properties_;
};
class derived : public base<derived>
{
public:
void foo()
{
properties_.emplace("member", std::unique_ptr<property_base>(new property<int>(value_)));
}
private:
int value_;
};
I know this is not considered a good pattern since I'm doing a bad thing - accessing the derived class member variables before their constructors have been run, but I only store the reference, so as far as I do not mess this up and start doing anything else with them this should be fine. That said, are there any cases/scenarios which I have overlooked and in which calling foo() which ONLY stores the references in the map would cause any errors?
Is it possible to have a different type definition based on which derived class is instantiated?
Say I have a parent class with a virtual function func(), two int members and a vector of type myType, and two child classes, which share the same int members, and the vector, but their implementation of func() require myType to be slightly different.
For example:
class Parent {
protected:
int myMember;
int myOtherMember;
std::vector<myType> vec;
public:
Parent(variable);
virtual int func() = 0;
}
class Child1 : public Parent {
private:
typedef <some type definiton> myType;
public:
Child1(variable) : Parent(variable){};
int func() {return someFunc();};
}
class Child2 : public Parent {
private:
typedef <some other type definiton> myType;
public:
Child2(variable) : Parent(variable){};
int func() {return someOtherFunc();};
}
Can I do something like this? when I have tried it, it creates a circular dependency in the header files, because class Parent is required to be included first, but then it requires myType to be defined.
Is there a way of forward declaring myType depending on class? or do I just need to include a different vector of myType in each class like so:
class Parent {
protected:
int myMember;
int myOtherMember;
public:
Parent(variable);
virtual int func() = 0;
}
class Child1 : public Parent {
private:
typedef <some type definiton> myType;
std::vector<myType> vec;
public:
Child1(variable) : Parent(variable){};
int func() {return someFunc();};
}
class Child2 : public Parent {
private:
typedef <some other type definiton> myType;
std::vector<myType> vec;
public:
Child2(variable) : Parent(variable){};
int func() {return someOtherFunc();};
}
This is a job for templateman!
First we declare Parent
template <class TYPE>
class Parent {
protected:
int myMember;
int myOtherMember;
std::vector<TYPE> vec;
public:
Parent(TYPE variable);
virtual int func() = 0;
};
Unfortunately a custom type contained within Child1 is out with this approach because the type needs to be declared before we can specialize a template on it. I'm using int and double here for ease. Replace as needed.
using Child1Type = int;
// or typedef int Child1Type; pre-C++11
class Child1 : public Parent<Child1Type> {
public:
Child1(Child1Type variable) : Parent(variable){};
int func() {return someFunc();};
};
using Child2Type = double;
class Child2 : public Parent<Child2Type> {
public:
Child2(Child2Type variable) : Parent(variable){};
int func() {return someOtherFunc();};
};
EDIT
Kicking myself for not getting this earlier (and burning way too much time because I knew it had to be possible, but was thinking in the wrong direction)
Declare the type up in Parent. Set the access based on who need to be able to see the type. Here I made Type public to test it out in main. The Type is declared in Parent and is visible to (and through because it's public) the Children.
Also stripped out everything that wasn't immediately necessary and used fixed width integer types so I could easily demonstrate the differences.
I think this is exactly what Pixelchemist was alluding to.
template <class TYPE>
class Parent {
public:
using Type = TYPE; // declare Type here
protected:
int myMember;
int myOtherMember;
std::vector<Type> vec; // visible here
public:
Parent(Type variable); // here
virtual ~Parent(){}
virtual int func() = 0;
};
class Child1 : public Parent<uint16_t> { // complicated type needs to be reproduced
// only once, here in the specialization
public:
Child1(Type variable) : Parent(variable){};
};
class Child2 : public Parent<uint32_t> {
public:
Child2(Type variable) : Parent(variable){};
};
int main()
{
// and visible way down here in main through Child1 and Child2
std::cout << "Child 1: " << sizeof(Child1::Type) << std::endl;
std::cout << "Child 2: " << sizeof(Child2::Type) << std::endl;
}
output is
Child 1: 2
Child 2: 4
You could simply use templates:
template<class T>
struct Base
{
std::vector<T> v;
};
struct D1 : public Base<int>
{
// all stuff in here comes into play when deriving from Base is already done
// Thus, compiler cannot know any typedefs from here inside Base...
};
struct D2 : public Base<double>
{
};
where you cannot use a typedef from derived in base class. See CRTP refer to typedef in derived class from base class.
This is what templates are for:
<template typename T>
class Child : public Parent {
private:
std::vector<T> vec;
public:
Child(variable) : Parent(variable) {};
int func() { return someOtherFunc(); };
}
Then Child is declared as something like:
Child<int> myChildInstance(10);
What I wish to do is have a class that contains a map of function pointers of a second class, but the name of the second class should not matter (cannot be hard coded into the first class) I would really like to be able to implement this WITHOUT using macros. I have followed the examples from learncpp.com on function pointers, but when passing them between classes I am really lost! My attempt is below:
#include <map>
class Class1;
typedef double(Class1::*memFunc)();
class Class1
{
private:
std::map<std::string, memFunc> funcMap;
public:
void addFunc(std::string funcName, memFunc function)
{
funcMap.insert(std::pair<std::string, memFunc>(funcName, function));
}
};
class MyClass
{
public:
MyClass()
{
//How do I add member function getValue() to Class1?
class1.addFunc("new function", getValue());
}
double getValue()
{
return 0;
}
private:
Class1 class1;
};
The name of the class is a part of the type of the function pointer, which becomes part of the map's type, which becomes part of MyClass. Depending on how strong is the requirement "cannot be hard coded", perhaps a template would be sufficient?
#include <string>
#include <map>
template<typename T>
class Class1
{
typedef double(T::*memFunc)();
std::map<std::string, memFunc> funcMap;
public:
void addFunc(std::string funcName, memFunc function)
{
funcMap.insert(std::pair<std::string, memFunc>(funcName, function));
}
};
class MyClass
{
public:
MyClass()
{
class1.addFunc("new function", &MyClass::getValue);
}
double getValue()
{
return 0;
}
private:
Class1<MyClass> class1;
};
int main()
{
MyClass mc;
}
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.
}
}