library implementation for reference counting classes - c++

I have a class like so:
Texture
{
int ID
public:
Texture(std::string name){ ID = make_texture(name); }
~Texture(){ delete_texture(ID); }
};
but the problem is that when I move the class, the destructor is called so the ID is now invalid.
my current implementation would be something like:
Texture
{
static std::unordered_map<int> m;
int ID
public:
Texture(std::string name){
ID = make_texture(name);
m[ID]++;
}
Texture(Texture& obj){ *this = obj; }
Texture &operator=(Texture& obj){
ID = obj.ID;
m[ID]++;
}
~Texture(){
if (!--m[ID])
delete_texture(ID);
}
};
//was coded in stack overflow so syntax may be a bit off
but what would really be nice is a class I could inherit from like:
Texture : public ref_count<int>
{
int ID
public:
Texture(std::string name){ ID = make_texture(name); }
key(){return ID;} // inherited from ref_count
on_delete(){ delete_texture(ID); } // inherited from ref_count
};
so my question is: does a convenient class like this exist in the standard / boost library? Or what is the best way to achieve this without implementing my own reference counting.

To expand on my comment. You need Texture objects to be shared references to the same ID, so it's ID that needs to be wrapped in some reference counting type for Texture to hold. That's exactly a use case for std::shared_ptr. All you need is a custom deleter that would delete_texture as part of freeing the managed integer.
class Texture
{
std::shared_ptr<int> ID;
public:
Texture(std::string name) :
ID{ new int(make_texture(name)),
[](int* id_ptr) {
delete_texture(*id_ptr);
delete id_ptr;
}
}
{}
};
And that's it. The copy/move/dtor of Texture can now be implicitly generated by the compiler, since it relies on the correct behavior of std::shared_ptr.

Related

How to properly store inherited objects in std::map for good accessibility?

This is my first C++ related programming question. I consider myself a beginner in programming even though I have dealt with C++ in some ways for about half a year. My question yields at an inheritance problem that I recently faced in my work.
I have a class NodeMaster that should handle a container (right now a map) of different child objects inherited from the same base class NBase - accessing them, change data, ...
// Base class
class NBase
{
private:
int m_ID;
public:
NBase() { m_ID = 0; };
~NBase() {};
...
}
// Child class
class NSampler : NBase
{
private:
int m_ID;
std::string m_state;
public:
NSampler(std::string state) : {
m_ID = 1;
m_state = state;
}
...
}
The childs of NBase are 'registered' into the map via some arbitrary index:
#include "NBase.h"
class NodeMaster
{
private:
std::map<int, std::shared_ptr<sbr::NBase>> m_mpNodes;
public:
void register_node(int nIdx, std::shared_ptr<sbr::NBase> pNode)
{
this->m_mpNodes.insert(std::pair<int, std::shared_ptr<sbr::NBase>>(nIdx, pNode->clone()));
}
std::shared_ptr<sbr::NBase> get_node(int idx)
{
std::map<int, std::shared_ptr<sbr::NBase>>::iterator itr;
for (itr = this->m_mpNodes.begin(); itr != this->m_mpNodes.end(); ++itr) {
if (itr->first == idx) {
return itr->second;
}
}
}
I read about this problem on SO to imporve my solution step-by-step and also read about the issue of Object Slicing. Therefore I put the objects into a std::shared_ptr to guarantee the 'polymorphic behaviour' throughout the process. So far everything is good and I can add the Child class objects to the container via
std::shared_ptr<sbr::NSampler> sampler(std::make_shared<sbr::NSampler>("SAMPLER_INIT"));
NodeMaster nodeMater;
nodeMaster.register_node(sampler->get_ID(), sampler);
Now what gives me headaches is how to properly access the elements of m_mpNodes later in the code ... The nodeMaster itself is passed to another function by reference pre_process_lin(nodeMaster, m_Links) and to access the elements inside this function I expected to just write e.g. nodeMaster.get_node(1) but that does not return the inherited object 'NSampler' but rather 'NBase' ... to retrieve 'NSampler' I had to use a dynamic_cast for smart pointers:
nodeMaster.get_node(1); // NBase
...
std::shared_ptr<sbr::NSampler> test_sampler = std::dynamic_pointer_cast<sbr::NSampler>(nodeMaster.get_node(1)); // NSampler
To get this going I had to add a copy ctor to both the NBase and the NSampler (for using the covariance feature of C++) and considering that I deal with smart pointers I read this blog post to implement the copy ctor into the classes
// Base class
class NBase
{
private:
int m_ID;
public:
NBase() { m_ID = 0; };
~NBase() {};
public:
std::shared_ptr<NBase> clone() const
{
return std::shared_ptr<NBase>(this->clone_impl());
}
private:
virtual NBase* clone_impl() const = 0;
...
}
// Child class
class NSampler : NBase
{
private:
int m_ID;
std::string m_state;
public:
NSampler(std::string state) : {
m_ID = 1;
m_state = state;
}
public:
std::shared_ptr<NSampler> clone() const
{
return std::shared_ptr<NSampler>(this->clone_impl());
}
private:
virtual NSampler* clone_impl() const override
{
return new NSampler(*this);
}
...
}
With this setup I solve my problem of stacking together a bunch of inherited class objects into some container (map), but since this specific copy-ctor is called (in order to be able to add them to the container) the initial member variables (e.g. m_state) get overwritten after 're-calling' the objects from the map.
Is there a better way to wrap the process of inheritance, packing to container and unpacking without losing object data on the run due to the copy-ctor above?

Call a derived class' (non-virtual) function in the base class' Destructor

Suppose we have the following class template:
template<typename T>
class Object
{
public:
Object() = default;
Object(const Object&) = delete;
Object(Object&& other) noexcept
{
if (this != &other)
{
static_cast<T*>(this)->Release();
m_Id = std::exchange(other.m_Id, 0);
}
}
auto operator=(const Object&) = delete;
Object& operator=(Object&& other) noexcept
{
if (this != &other) {
static_cast<T*>(this)->Release();
m_Id = std::exchange(other.m_Id, 0);
}
return *this;
}
~Object()
{
static_cast<T*>(this)->Release();
m_Id = 0;
}
protected:
std::uint32_t m_Id;
};
(Please ignore the duplication in the move constructor and move assignment operator for the moment)
This class is meant to act as a base class for OpenGL object wrappers. Following is an example use:
class VertexBuffer : public Object<VertexBuffer>
{
public:
VertexBuffer()
{
glGenBuffers(1, &m_Id);
...
}
void Release()
{
glDeleteBuffers(1, &m_Id);
}
};
The Object<T> class template is supposed to take care of the bookkeeping.
The reason for doing this is that the pattern in the Object<T> class is repeated the exact same way for (almost) every OpenGL object wrapper that might be written. The only difference is the creation and deletion of the objects which is handled by the constructor and the Release() function in this example.
Now the question is whether this (Object<T>::~Object() to be specific) taps into UB land? Undefined Behavior Sanitizer doesn't report any errors but I've never done this, so I though of asking people with more experience to make sure.
Short answer: Yes, this is undefined behaviour, don't do that.
Long answer:
The destruction of VertexBuffer invokes first ~VertexBuffer() and then invokes ~Object<VertexBuffer>() afterwards. When ~Object<VertexBuffer>() is invoked the VertexBuffer "part" of the object has already been destroyed, i.e. you are now doing an illegal downcast via static_cast (the remaining valid part of the object is a Object<VertexBuffer>, not a VertexBuffer).
And undefined behaviour permits the compiler to do ANYTHING - it might even (appear to) work, only to suddenly stop working (or only work when you build in Debug mode, but not when in Release). So, for your own sake, please don't do that.
Don't do that. That'll cause an undefined behavior.
Instead, implement the template class as a derived class, like the following example.
class BufferGrandBase {
protected:
GLuint id;
};
template<class B>
class Buffer : public B {
public:
Buffer() {
B::Create();
}
~Buffer() {
B::Destroy();
}
};
class VertexBufferBase : public BufferGrandBase {
public:
void Create() { glGenBuffers(1, &id); }
void Destroy() { glDeleteBuffers(1, &id); }
};
typedef Buffer<VertexBufferBase> VertexBuffer;
This pattern will also simplify implementing constructors and operators.
If you have a "thing" that holds an Object<T> where T is the Crtp-type, that "thing" is likely a template anyway.
So instead of holding an Object<T>, why don't you just hold a T, which is the full type that inherits from Object<T>. If that is destroyed it will call T::~T() automatically.
In addition, perhaps you want to do private or protected inheritance from Object<T> to discourage users from slicing the Crtp-type.
Edit: You can simplify your Ts by moving the actual work into Object<T>:
class VertexBuffer : public Object<VertexBuffer>
{
public:
VertexBuffer() : Object<VertextBuffer>(glGenBuffers, glDeleteBuffers, 1) {
... // more stuff you did in your original constructor
}
};
Where Object looks like this in addition to what you already have:
template <typename T>
class Object {
void (*release)(int, std::uint32_t*);
int i;
Object() = delete;
Object(void (*acquire)(int, std::uint32_t*), void (*release)(int, std::uint32_t*), int i = 1) : release{release}, i{i} {
acquire(i, &m_Id);
}
~Object() {
release(i, &m_Id);
}
// rest of your Object class
};
This is close to the model of std::unique_ptr<> with a custom deleter. But it doesn't quite fit because std::unique_ptr has to hold a pointer and this case needs an integer handle-type.
So here is a brief example. It is general good advice to prefer inclusion over inheritance so I have deliberately placed the helper object inside the owning class.
All I'm really trying to demonstrate here is that there are a number of ways to customise behaviours in templates beyond call members of instances.
#include <iostream>
#include <memory>
typedef size_t gd_size;
typedef int gd_handle;
void gen_buffers(gd_size size,gd_handle*buffs);
void del_buffers(gd_size size,gd_handle*buffs);
typedef void (*gd_func)(gd_size,gd_handle*buff);
template<gd_func gfunc,gd_func dfunc> class GenDel{
public:
GenDel(){gfunc(1,&buff);}
~GenDel(){dfunc(1,&buff);}
int get()const{return buff;}
private:
int buff;
GenDel(const GenDel&)=delete;
};
class BufferHolder{
public:
BufferHolder(){}
void do_thing() const{
std::cout<<"using "<<buffer.get()<<'\n';
}
private:
GenDel<gen_buffers,del_buffers> buffer;
};
int main() {
BufferHolder b;
BufferHolder c;
b.do_thing();
return 0;
}
int seed{0};
void gen_buffers(gd_size size,gd_handle*buffs){
for(size_t i{0};i<size;++i){
buffs[i]=++seed;
std::cout << "generated "<< buffs[i] << '\n';
}
}
void del_buffers(gd_size size,gd_handle*buffs){
for(gd_size i{0};i<size;++i){
std::cout << "deleted "<< buffs[i] << '\n';
}
}

c++ Mapping class to number

I recently started with c++ development. I've come to a problem of which I am not able to solve, given that I am unaware if the following is possible.
I want to create a mapping between a number and class, which are derived from an abstract class.
Essentially what I would like to be able to do is create a factory method that can create a new instance of a class based on a given number associated with that class.
I know that I could do the following...
Vehicle *Vehicle::from_type(byte type)
{
switch(type)
{
case 0x00: return new Bicyle();
case 0x01: return new Car();
...
case 0x10: return new Truck();
}
return null;
}
..., but I'd rather not as I want to keep it DRY.
It there a way where one can do something along the lines of this:
// I know this is incorrect syntax
const map<byte, class extends Vehicle> VEHICLE_MAPPING = {{0x00, Bicyle}, {0x01, Car}, ..., {0x10, Truck}};
Vehicle *Vehicle::from_type(byte type)
{
return new VEHICLE_MAPPING[type]();
}
I can see how your approach could work with usage of std::map<uint8_t, std::unique_ptr<Vehicle>>, but there is a problem - you wouldn't be able to initialise that map with initializer_list, since it copies the elements and, as we all know, std::unique_ptr cannot be copied. You would have to create an init() function to initialise the map that would use similar logic to your Vehicle *Vehicle::from_type(byte type), which would simply be pointless given you already have your function.
Furthermore, I disagree that your first solution violates DRY. It is actually correct in a sense that you won't be forced to use switch or ifs elsewhere in the code. I'd definitely stick with it.
The final note - you could use std::map<uint8_t, std::shared_ptr<Vehicle>> instead of std::map<uint8_t, std::unique_ptr<Vehicle>> and initialise it with initializer_list, since std::shared_ptr can be copied, but I wouldn't advise that since it wrongly indicates the usage of shared_ptr. If you somehow feel forced to do so, here is an example:
class Base{ public: virtual ~Base() = default; };
class Derived1 : public Base{};
class Derived2 : public Base{};
class derived_factory{
private:
derived_factory();
static inline std::map<uint8_t, std::shared_ptr<Base>> base_map = {
{0x00, std::make_shared<Derived1>()},
{0x01, std::make_shared<Derived2>()}
};
public:
static std::unique_ptr<Base> from_type(uint8_t type)
{
return std::make_unique<Base>(*base_map[type]);
}
};
int main()
{
auto ptr = derived_factory::from_type(0x00);
// ptr is of a type std::unique_ptr<Base> and points to Derived1 object
}
Additional note that should be a final discouragement of using this solution is that it's quite slow. It constructs the objects in a map and does nothing with them except for keeping them as 'templated' copy examples.
If they're all derived from a base class, you can use the factory pattern, e.g., from Loki's implementation (see Modern C++ Design for the details, though that book is pre-C++11).
The following creates some concrete vehicles and puts them in a vector and then calls the drive() method on each of them:
#include <iostream>
#include <memory>
#include <vector>
#include "factory.h"
struct Vehicle
{
virtual ~Vehicle() = default;
virtual void drive() = 0;
};
struct Car : Vehicle
{
static constexpr auto ID = 1;
void drive() override { std::cout << "Car\n"; }
};
struct Truck : Vehicle
{
static constexpr auto ID = 2;
void drive() override { std::cout << "Truck\n"; }
};
// Create the factory object
auto g_factory = MyUtil::Factory<std::unique_ptr<Vehicle>, int>{};
void RegisterTypesWithFactory()
{
// We pass in creator functions for each type. Note that these
// could be lambdas or some other freestanding function and they
// could accept parameters.
g_factory.Register( Car::ID, &std::make_unique<Car> );
g_factory.Register( Truck::ID, &std::make_unique<Truck> );
}
int main()
{
// Configure the factory
// Note: Registration can be done any time, e.g., later based on input
// from a file. I do them all at once here for convenience of illustration.
RegisterTypesWithFactory();
// Create some objects with the factory
auto vehicles = std::vector<std::unique_ptr<Vehicle>>{};
vehicles.emplace_back( g_factory.Create( Car::ID ) );
vehicles.emplace_back( g_factory.Create( Truck::ID ) );
// Do something with the objects
for( const auto& v : vehicles )
{
v->drive();
}
}
Which prints:
Car
Truck
See it run live on Wandbox.

Proper design setup for derived classes with common attributes but different values

So I can think of a few ways to do this but I feel like I am just retyping the same thing with each new subclass. Is there a design pattern where I can set up the full structure for my subclasses in a way where I reduce the amount of code needed for implementation (and also enforce proper implementation if possible?)
This seems simple but the ideas I've had don't work, and the best I've found is to either hard code in the parameters when calling the constructor or to set up new constants within each child class then use those.
What I currently have is something like this:
"parent.hpp"
class Parent {
private:
std::string name;
int someValue;
protected:
Parent(std::string name, int someValue); // NOTE: There will be 7 parameters/attributes that need initial base values
void setName(std::string name) { this->name = name; }
void setSomeValue(int someValue) { this->someValue = someValue; }
public:
std::string getName() { return this->name; }
int getSomeValue() { return this->someValue; }
};
"parent.cpp"
Parent::Parent(std::string name, int someValue) {
setName(name);
setSomeValue(someValue);
}
"child.hpp"
class Child : public Parent {
public:
Child();
};
"child.cpp - option 1"
static const std::string DEFAULT_NAME = "Jon";
static const int DEFAULT_SOME_VALUE = 100;
Child::Child() : Parent(DEFAULT_NAME, DEFAULT_SOME_VALUE) {
// other stuff if needed
}
"child.cpp - option 2"
Child::Child() : Parent("Jon", 100) {
// other stuff if needed
}
There will be virtual methods and such I'll add later, but for now I just want to know of the right design pattern for having (potentially) many subclasses. There are also more parameters that will be in common which are all int values. It would seem unclear to me to have the constructors be Child::Child("string", 1, 2, 3, 4, 5, 6) albeit it would be easier to implement new subclasses.
On the other hand if I am just retyping the boiler plate constants for the base values in each subclass, the constructors will be more descriptive, but there would be a lot of code reuse.
It would seem to me what I would want to do is have virtual protected constants in the Parent class which the Child classes would need to define, then call those from the constructors, but that is not allowed. Is one of the two options a better one? Is there a better "long-term" setup for this?
I looked through all of the Similar Questions and the closest I found was this: Proper way to make base class setup parent class. Though I'm not really sure if that idea would fix my issue or make anything clearer.
Another idea I had was to call pure virtual methods from the default constructor, but as I learned that is also not allowed.
I would use another object to hold the state like Ami, although I would have done it for a different reason. Since the state is a separate class, you can fully construct it before the actual Parent and Child are constructed, and it can have its own hierarcy.
header
class Parent {
protected:
struct ParentState {
std::string name;
int someValue;
};
Parent(ParentState);
void setName(std::string name) { data.name = name; }
void setSomeValue(int someValue) { data.someValue = someValue; }
public:
std::string getName() { return data.name; }
int getSomeValue() { return data.someValue; }
private:
ParentState data;
};
class Child : public Parent {
struct ChildDefaults : public Parent::ParentState {
ChildDefaults();
};
public:
Child();
};
implementation
Parent::Parent(ParentState init) {
// since you have setters, they should be used
// instead of just data=init;
setName(init.name);
setSomeValue(init.someValue);
}
Child::ChildDefaults::ChildDefaults(){
name = "Jon";
someValue = 100;
}
Child::Child() : Parent(ChildDefaults()){
// other stuff if needed
}
If you put the ParentState and ChildDefault classes in a separate file, you can use that file to put all the defaults in one place where you can easily look them up or change them. They also might be prettier if they are not hidden inside the classes, forcing the extra scope syntax.
addendum:
To put the whole default settings heirarchy together in its own header, just move them all to one header. Be sure to do an include guard to avoid multiply defining the constructors.
#ifndef THE_DEFAULTS_H
#define THE_DEFAULTS_H
struct ParentState {
std::string name;
int someValue;
};
struct ChildDefaults : public Parent::ParentState {
ChildDefaults() {
name = "Jon";
someValue = 100;
}
};
// more default settings for other classes
#endif
Perhaps you could combine here two ideas:
Avoiding a large number of args passed to a function in general (including a ctor).
Method chaining.
(The first one is more fundamental here, and the second one is less essintial, and is here just for improved readability.)
In more detail:
Having any function, a ctor of a base class in particular, taking 7 parameters, seems very verbose & fragile. Suppose you realize that you needed to add another parameter. Would you now have to go over all the derived classes? That's problematic.
So let's start with something like:
class Parent
{
protected:
explicit Parent(const ParentParams &params);
};
And ParentParams looks something like this:
class ParentParams
{
public:
// Initialize with default stuff.
ParentParams();
// Changing only the foo aspect (via method chaining).
ParentParams &setFoo(Foo foo_val)
{
m_foo = foo_val;
return *this;
}
// Changing only the bar aspect (via method chaining).
ParentParams &setBar(Bar bar_val)
{
m_bar = bar_val;
return *this;
}
// Many more - you mentioned at least 7.
....
};
Now a child could look something like this:
// A child that happens to have the property that it changes foo and bar aspects.
class FooBarChangingChild :
public Parent
{
public:
FooBarChangingChild();
};
And in its implementation:
// Static cpp function just creating the params.
static ParentParams makeParams()
{
// Note the clarity of which options are being changed.
return ParentParams()
.setFoo(someFooVal)
.setBar(someBarVal);
}
FooBarChangingChild::FooBarChangingChild() :
Parent(makeParams())
{
}

Accessing derived class members with a base class pointer

I am making a simple console game in C++
I would like to know if I can access members from the 'entPlayer' class while using a pointer that is pointing to the base class ( 'Entity' ):
class Entity {
public:
void setId(int id) { Id = id; }
int getId() { return Id; }
protected:
int Id;
};
class entPlayer : public Entity {
string Name;
public:
void setName(string name) { Name = name; }
string getName() { return Name; }
};
Entity *createEntity(string Type) {
Entity *Ent = NULL;
if (Type == "player") {
Ent = new entPlayer;
}
return Ent;
}
void main() {
Entity *ply = createEntity("player");
ply->setName("Test");
ply->setId(1);
cout << ply->getName() << endl;
cout << ply->getId() << endl;
delete ply;
}
How would I be able to call ply->setName etc?
OR
If it's not possible that way, what would be a better way?
It is possible by using a cast. If you know for a fact that the base class pointer points to an object of the derived class, you can use static_cast:
Entity* e = /* a pointer to an entPlayer object */;
entPlayer* p = static_cast<entPlayer*>(e);
p->setName("Test");
If you don't know for sure, then you need to use dynamic_cast and test the result to see that it is not null. Note that you can only use dynamic_cast if the base class has at least one virtual function. An example:
Entity* e = /* a pointer to some entity */;
entPlayer* p = dynamic_cast<entPlayer*>(e);
if (p)
{
p->setName("Test");
}
That said, it would be far better to encapsulate your class's functionality using polymorphism (i.e. virtual functions).
Speaking of virtual functions, your class hierarchy as implement has undefined behavior: you can only delete an object of a derived type through a pointer to one of its base classes if the base class as a virtual destructor. So, you need to add a virtual destructor to the base class.
I would consider doing something like this:
public:
void setId(int id)
{
Id = id;
}
void virtual setName( string name ) = 0; // Virtual Function
string virtual getName() = 0; // Virtual Function
int getId() { return Id; }
protected:
int Id;
};
class entPlayer : public Entity {
string Name;
public:
entPlayer() {
Name = "";
Id = 0;
}
void entPlayer::setName(string name) { // Must define function
Name = name;
}
string entPlayer::getName() { return Name; } // again must define function here
};
You can do a dynamic cast:
entPlayer * pPlayer = dynamic_cast<entPlayer *>(pointer_to_base);
This will (if successful) result in a derived pointer.
Otherwise NULL is returned.
C++ makes what you are trying to do really awkward, because this is probably not what you should be doing, and it is trying to lead you to good object-oriented design. In fact, by default, compilers often disable run-time type information (RTTI), which is needed to make dynamic_cast work.
Without knowing your broader context, it's hard to say what you should do instead. What I can say is that if you wanted a more specific pointer, you should have put a ring on it you almost certainly shouldn't use a function that returns an Entity*, and there is probably a better approach.