C++ operator->() overload - c++

Okay, since it's my first question, let me try again. I edited post and changed code to make it easier for you all to understand.
template <typename T>
class Structure
{
protected:
DWORD64 _instanceAddress;
T _structPointer;
public:
Structure<T>(DWORD64 instanceAddress);
~Structure();
T* operator->();
};
template <typename T>
T* Structure<T>::operator->()
{
Driver::ReadMemory( _instanceAddress, sizeof(T), &_structPointer );
return static_cast<T*>( &_structPointer );
}
struct C
{
int some_value;
}
struct B
{
C *pointer_to_C;
}
struct A
{
B *pointer_to_B;
}
//CODE
Structure<A> myStructure(DWORD64 AddressInMemory);
myStructure->pointer_to_B->pointer_to_C->some_value;
I'm reading other process memory through driver. Address of structure I'm trying to reach is static, so there is nothing to worry about. Is there any way that I can change my memory reading class to make it work like I've specified in bottom line of code? The ideal situation would be to do some changes in operator->() overload to do some checks regarding type user is trying to reach.
It should allow to define only lowest Structure in pointer chain and then just dereference it like its being done normally on mother-process raw memory.
So I'm imagining it would be something like that:
template <typename T>
T* Structure<T>::operator->(type_of_desired_variable var_name)
check if var_name is int or float
if not then define new Structure<type_of_desired_variable> and store it somewhere, then call its operator->()

Related

How to generalize this C++ wrapper around a C 'class'?

I am writing a C++ wrapper around a C library. Here is an example of my strategy.
// header file
class LibrdfUri { // wrapper around librdf.h librdf_uri*
/*
* If the deleter of std::unique_ptr is an empty
* class then it can do some optimizations and
* not actually store the deleter object.
* Otherwise it has to accommodate extra space for
* the deleter, which is unnecessary
* https://stackoverflow.com/questions/61969200/what-is-the-purpose-of-wrapping-this-private-deleter-function-in-a-struct/61969274#61969274
*/
struct deleter {
// turns deleter into a functor. For passing on to unique_ptr
void operator()(librdf_uri *ptr);
};
// automate management of librdf_uri* lifetime
std::unique_ptr<librdf_uri, deleter> librdf_uri_;
public:
LibrdfUri() = default;
explicit LibrdfUri(const std::string& uri); // construct from string
librdf_uri *get(); // returns the underlying raw pointer
};
// implementation
void LibrdfUri::deleter::operator()(librdf_uri *ptr) {
librdf_free_uri(ptr); // this is the C library function for destruction of librdf_uri
}
LibrdfUri::LibrdfUri(const std::string &uri) {
// create pointer to underlying C library 'object'
librdf_uri_ = std::unique_ptr<librdf_uri, deleter>(
librdf_new_uri(World::getWorld(), (const unsigned char *) uri.c_str()) // World::getWorld is static. Returns a pointer required by librdf_new_uri
);
}
librdf_uri *LibrdfUri::get() {
return librdf_uri_.get();
}
// and is used like so:
LibrdfUri uri("http://uri.com");
librdf_uri* curi = uri.get(); // when needed
This works for the single type librdf_uri* which is a part of the underlying library however I have lots of these. My question is double barrelled. The first part concerns the best general strategy for generalizing this wrapper to other classes while the second is concerns the implementation of that strategy.
Regarding the first part, here are my thoughts:
1. I could implement each class manually like I've done here. This is probably the simplest and least elegant. Yet it still might be my best option. However there is a small amount of code duplication involved, since each CWrapper I write will essentially have the same structure. Not to mention if I need to change something then I'll have to do each class individually.
2. Use an base class (abstract?)
3. Use a template
The second part of my question is basically: if I implement either option 2 or 3 (which I think might even be just a single option) how would I do it?
Here is a (vastly broken) version of what I'm thinking:
template<class LibrdfType>
class CWrapper {
struct deleter { ; //?
void operator()(LibrdfType *ptr) {
// ??
};
}
std::unique_ptr<LibrdfType, deleter> ptr;
public:
CWrapper() = default;
LibrdfType *get() {
ptr.get();
};
};
Then, LibrdfUri and any other C class I need to wrap, would just subclass CWrapper
This is a better deleter:
template<auto f>
using deleter=std::integral_constant< std::decay_t<decltype(f)>, f >;
use:
deleter<librdf_free_uri>
is a stateless deleter that calls librdf_free_uri.
But we don't need that I think. Here is what I might do:
There are 3 pieces of information you need.
How to construct
How to destroy
What type to store
One way is to define ADL baser helpers with famous names that you override to delete/construct.
template<class T>struct tag_t{};
template<class T>constexpr tag_t<T> tag{};
template<class T>
void delete_wrapptr(T*)=delete;
struct cleanup_wrapptr{
template<class T>
void operator()(T* t)const{ delete_wrapptr(t); }
};
template<class T>
using wrapptr=std::unique_ptr<T, cleanup_wrapptr>;
template<class T>
wrapptr<T> make_wrapptr( tag_t<T>, ... )=delete;
now you just have to write overloads for make and delete.
void delete_wrapptr(librdf_uri* ptr){
librdf_free_uri(ptr); // this is the C library function for destruction of librdf_uri
}
librdr_uri* make_wrapptr(tag_t<librdf_uri>, const std::string &uri) {
return librdf_new_uri(World::getWorld(), (const unsigned char *) uri.c_str()); // World::getWorld is static. Returns a pointer required by librdf_new_uri
}
and you can;
wrapptr<librdf_uri> ptr = make_wrapptr(tag<librdf_uri>, uri);
the implementation becomes just overriding those two functions.
make_wrapptr and delete_wrapptr overloads you write need to be visible at creating point, and in the namespace of T, tag_t or cleanup_wrapptr. The implementations can be hidden in a cpp file, but the declaration of the overload cannot.

How do I get the value of this void* back?

I have a void pointer of which I can set the value just fine (at least I think I did it right). But when I try to get the value of what is stored there, all I get nothing back. Doesn't matter if the void* points to a string or int or anything else.
What am I missing here?
class Vertex2{
public:
int _id;
void *_data;
template<typename T>
T getData() {
T *value = (T*)_data;
return *value;
}
template <typename T>
void setData(T data) {
_data = &data;
}
};
void setData(T data) receives data by value.
Setting a pointer to data therefore is only valid for the lifetime of that function call.
After that, the pointer dangles, and dereference behaviour is undefined.
template <typename T>
void setData(T data) {
_data = &data;
}
let's check what's going on here. You store a pointer to a local variable (method argument actually). Right after you leave the method the local var is destroyed and its memory is free to be reused. Now your void* points to the same memory address but the memory can contain anything.
Try it like this:
// the entire class should be templated and you should not cast the data to void
template<typename T>
class Vertex2
{
public:
int _id;
// data is no longer void
T m_data;
// now returning a const pointer to your data and protect it against manipulation from outside
getData() const {
return m_data;
}
// was setting the address of a temporary, that will not work. Now it takes a copy and moves that to the member.
void setData(T data) {
m_data = std::move(data);
}
};
I have added comments in the code.
As to your code
template <typename T>
void setData(T data) {
_data = &data;
}
Do not do that. You store the address to the temporary copy of data. This will go wrong!
void *_data;
Do not store the data as void, template the class like this:
template<typename T>
class Vertex2
{
T m_data;
.
.
.
There's nothing stored there.
You set the pointer to point to a function argument, that then went out of scope.
You can cast as much as you like, but that object has gone!
This design won't work unless you dynamically allocate.
Consider a std::variant or something instead.

Const correctness in struct initialization

I'm playing with C++ and const-correctness right now.
Assume you have the following structure
template <typename T>
struct important_structure {
public:
T* data;
int a;
important_structure(const T& el, int a);
void change();
};
template <typename T>
void important_structure<T>::change() {
//alter data field in some way
}
template <typename T>
important_structure <T>::important_structure(const T& el, int a) : data(&el), a(a) //error line {
};
int main() {
important_structure<int>* s = new important_structure<int>{5, 3};
}
When compiling with std=c++11, the compiler returns the following error:
invalid conversion from ‘const int*’ to ‘int*’
Now, I know it's unsafe to cast a const int* to int*. The problem is that I have a data structure and I don't want to put the field data as a constant.
However, I don't want to remove the const qualifier in the constructor since, I think, it's informative for future developers: it clearly says that el won't be modified by the function. Still the field data may be modified by some other function in important_structure.
My question is: How can I deal with fields which are initialized in the costructor and altered in some other function?
Most of const correctness deals with simple answers, but no question (I think) deals with scenarios where a const parameter is passed to a data structure and then such data structure is altered by someone else.
Thanks for any kind reply
passing el as a const reference doesn't just mean the function will not change el during the run of the function, it means because of this function call, el won't be changed at all. And by putting the address of el into non-const data, you violate that promise.
So, the clean solution, if you indeed want to change data, is removing the const. since it is not informative to future developers, but misleading. Casting away the const would be very bad here.
Let's use a simple class as T type of important_struct:
class Data
{
public:
Data() : something(0){}
Data(int i) : something(i){}
Data(const Data & d) : something(d.something){}
//non-const method: something can be modified
void changeSomething(int s){ something += s; }
//const method: something is read-only
int readSomething() const { return something; }
private:
int something;
};
This class has a very simple, yet well encapsulated, status, i.e. the int something field, which is accessed through methods in a very controlled way.
Let (a simplified version of) important_structure hold an instance of Data as a private field:
template <typename T>
struct important_structure
{
public:
important_structure(T * el);
void change();
int read() const;
private:
T* data;
};
We can assign a Data instance to an important_structure instance this way:
important_structure<Data> s(new Data());
The instance is assigned in construction:
template <typename T>
important_structure <T>::important_structure(T * el) : data(el) {}
Now the great question: do important_structure take ownership of the Data instances it holds? The answer must be made clear in documentation.
If it is yes, important_structure must take care of memory cleanup, e.g. a destructor like this one is required:
template<typename T>
important_structure<T>::~important_structure()
{
delete data;
}
Notice that, in this case:
Data * p = new Data()
// ...
important_structure<Data> s(p);
//p is left around ...
another pointer to the Data istance is left around. What if someone mistakenly call delete on it? Or, even worse:
Data d;
// ...
important_structure<Data> s(&p); //ouch
A much better design would let important_structure own its own Data instance :
template <typename T>
struct important_structure
{
public:
important_structure();
void change();
// etc ...
private:
T data; //the instance
};
but this is maybe simplistic or just unwanted.
One could let important_structure copy the instance it will own:
template<typename T>
important_structure<T>::important_structure(const T &el)
{
data = el;
}
the latter being the constructor provided in the question: the object passed won't be touched, but copied. Obviously, there are two identical Data objects around, now. Again, the result could not be what we needed in the first place.
There is a third way, in the middle: the object is instantiated outside the owner, and moved to it, using move semantics.
As an example, let's give Data a move assignment operator:
Data & operator=(Data && d)
{
this->something = d.something;
d.something = 0;
return *this;
}
and let important_structure provide a constructor which accepts an rvalue reference of T:
important_structure(T && el)
{
data = std::move(el);
}
One can still pass a Data instance using a temporary as the required rvalue:
important_structure<Data> s(Data(42));
or an existing one, providing the required reference from an lvalue, thanks to std::move:
Data d(42);
// ...
important_structure<Data> x(std::move(d));
std::cout << "X: " << x.read() << std::endl;
std::cout << "D: " << d.readSomething() << std::endl;
In this second example, the copy held by important_structure is considered the good one while the other is left in a valid but unspecified state, just to follow the standard library habits.
This pattern is, IMHO, more clearly stated right in code, expecially if considered that this code will not compile:
Data d(42);
important_structure<Data> x (d);
Whoever wants an instance of important_structure must provide a temporary Data instance or explicitly move an existing one with std::move.
Now, let the important_structure class be a container, as you asked in comment, so that data is somehow accessible from outside. Let's give a method like this to the important_structure class:
const T & owneddata() { return data; }
Now, we can use data const methods like this:
important_structure<Data> s(Data(42));
std::cout << s.owneddata().readSomething() << std::endl;
but calls to `Data' non-const methods will not compile:
s.owneddata().changeSomething(1000); //not compiling ...
If in need of it (hope not), expose a non-const reference:
T & writablereference() { return data; }
Now the data field is at full disposal:
s.writablereference().changeSomething(1000); //non-const method called
std::cout << s.owneddata().readSomething() << std::endl;
Using const T& el and data(&el) is a really bad idea, because it implies that you could write:
new important_structure<int>{5, 3};
But to write new important_structure<int>{5, 3}; would result in data holding an address that would no longer be valid immediately after calling the constructor.
If you want that the point data can be changed, but that the value where the pointer points to cannot be changed, then you want to write it that way:
template <typename T>
struct important_structure {
public:
T const * data;
int a;
important_structure(T const * el, int a);
void change();
};
template <typename T>
void important_structure<T>::change() {
//alter data field in some way
}
template <typename T>
important_structure <T>::important_structure( T const * el, int a) : data(el), a(a) { //error line
};
int main() {
int i = 5;
important_structure<int>* s = new important_structure<int>{&i, 3};
}

create dense dynamic array (array of value) as library

I tried to create packed array as a data structure for a game engine as described here:-
http://experilous.com/1/blog/post/dense-dynamic-arrays-with-stable-handles-part-1
In short, the structure stores values, instead of pointers.
Here is a draft.
template<class T> class Id{
int id;
}
template<class T> class PackArray{
std::vector <int>indirection ; //promote indirection here
std::vector <T>data;
//... some fields for pooling (for recycling instance of T)
Id<T> create(){
data.push_back(T());
//.... update indirection ...
return Id( .... index , usually = indirection.size()-1 .... )
}
T* get(Id<T> id){
return &data[indirection[id.id]];
//the return result is not stable, caller can't hold it very long
}
//... others function e.g. destroy(Id<T>) ...
}
The prototype works as I wished, but now I concern the beauty of old code.
For example, I had always created a new object like this:-
Bullet* bullet = new Bullet(gameEngine,velocity);
Now I must call :-
Id<Bullet> bullet = getManager()->create()->ini(velocity);
// getManager() usually return PackArray<Bullet>*
// For this data structure,
// if I want to hold the object for a long time, I have to cache it as Id.
Here are the questions :-
The new version of code is more ugly.
Should I avoid it? How to avoid it?
How to avoid / reduce programmer's-work of the above modification?
It is very tedious, when there are many of them scattering around.
(Edit) The scariest part is change in the type declaration e.g.
class Rocket{
std::vector<Bullet*> bullets;
//-> std::vector<Id<Bullet>> bullets;
void somefunction(){
Bullet* bullet = someQuery();
//-> Id<Bullet> bullet
}
}//These changes scatter around many places in many files.
This change (inserting the word "Id<>") means that the game logic has to know the underlying data structure that used to store Bullet.
If the underlying data structure would be changed again in future, I will have to manually refactor them one by one again (from Id<> to something else), i.e. lower maintainability.
(optional) What is the name of this data structure / technique?
As a library, should Id has a field of PackArray* to enable accessing the underlying object (e.g. Bullet*), without manager()?
Bullet* bullet = someId->getUnderlyingObject();
This behaviour of id sounds like handles, as in you don't give out information about the storage method, but guarantee access as long as the handle is valid. In the later respect handles behave like raw pointers: you won't be able to tell if it's valid (at least without the manager) and the handle might be reused at some point.
The question if changing from raw pointers to handles produces uglier code is very opinionated and I'd rather keep this objective: there's a balance between readably explicit and too much typing - everyone draws their own limits here. There's also advantages to having the calling site specify getManager: maybe there are multiple possible instances of these managers, maybe getting the manager requires locking and for multiple operations you want to lock only once. (You can support both of these cases in addition to what I present below.)
Let's use pointer/iterator notation to access the objects through our handles, reducing the amount of code changes necessary. Using std::make_unique and std::make_shared for reference, let's define make_handle to dispatch the creation to the right manager. I've adjusted PackArray::create a bit to make the following example more compact:
template<class T> class Handle;
template<class T> class PackArray;
template<class T, class... Args> Handle<T> make_handle(Args&&... args);
template<class T>
struct details {
friend class Handle<T>;
template<class U, class... Args> friend Handle<U> make_handle(Args&&... args);
private:
// tight control over who get's to access the underlying storage
static PackArray<T>& getManager();
};
template<class T>
class Handle {
friend class PackArray<T>;
size_t id;
public:
// accessors (via the manager)
T& operator*();
T* operator->() { return &*(*this); }
};
template<class T>
class PackArray {
std::vector<size_t> idx;
std::vector<T> data;
public:
template<class... Args>
Handle<T> create(Args&&... args) {
Handle<T> handle;
handle.id = data.size();
idx.push_back(data.size());
// enables non-default constructable types
data.emplace_back(std::forward<Args>(args)...);
return handle;
}
// access using the handle
T& get(Handle<T> handle) {
return data[idx[handle.id]];
}
};
template<class T, class... Args>
Handle<T> make_handle(Args&&... args) {
Handle<T> handle = details<T>::getManager().create(std::forward<Args>(args)...);
return handle;
}
template<class T>
T& Handle<T>::operator*() {
return details<T>::getManager().get(*this);
}
And the usage code would look like:
Handle<int> hIntA = make_handle<int>();
Handle<int> hIntB = make_handle<int>(13);
Handle<float> hFloatA = make_handle<float>(13.37f);
Handle<Bullet> hBulletA = make_handle<Bullet>();
// Accesses through the respective managers
*hIntA = 42; // assignment
std::cout << *hIntB; // prints 13
float foo = (*hFloatA + 12.26f) * 0.01;
applyDamage(hBulletA->GetDmgValue());
Every type needs a manager, i.e. if you don't define a default you'll get a compiler error. Alternatively you can provide a generic implementation (note: the initialisation of instance is not thread safe!):
template<class T>
PackArray<T>& details<T>::getManager() {
static PackArray<T> instance;
return instance;
}
You get special behaviour via template specialisation. You can even replace the manager type via template specialisation, allowing you to easily compare storage strategies (e.g. SOA vs. AOS).
template<>
struct details<Bullet> {
friend class Handle<Bullet>;
template<class U, class... Args> friend Handle<U> make_handle(Args&&... args);
private:
static MyBulletManager& getManager() {
static MyBulletManager instance;
std::cout << "special bullet store" << std::endl;
return instance;
}
};
And you can even make all of this const-correct (the same techniques as implementing custom iterators apply).
You may even want to extend the details<T> to a full traits type... It's all a balance between generalisation and complexity.

Is this concept for a reference counting memory manager for use with maps good?

I am trying to implement a memory management system to deal with pointers being stored in maps.
struct refmanager{ //since this class is only for inheritance
//and not for polymorphism their does not need to be a virtual destructor
int count;
refmanager():count(0){}
};
The first idea I had was to inherit the above struct into classes I am going to insert into maps as pointers.
template <class P> void ref(P ptr)
{
ptr->count+=1;
cout<<"increasing ref count\n";
}
template <class P> void deref(P ptr)
{
ptr->count-=1;
cout<<"decreasing ref count\n";
if (ptr->count==0)
delete ptr;
}
Than I was going to use the above template functions to increase and decrease the reference count. To make the system automatic I was going to use the template functions below as replacements for the normal map methods (note this is not complete and the clear map method was written for my test case and is not generic).
template <class M, class K, class V> void mapinsert(M &map, K key, V value)
{
ref(value);
map.insert(pair<K, V>(key, value));
}
template <class T> void clearmap(T input)
{
deref(input[1]);
input.clear();
}
From preliminary testing this idea works. But I don't have the knowledge to know if this will lead to possible disaster later. Can someone with more experience please let me know if this memory management concept is any good and if not when, where and why will it fail?
I only look at the space release of reference object (delete ptr), but where is the allocation?
You must ensure every reference objects are allocated in heap, not in stack.
value in ref(value); is a pointer? Because value is the template defined type, it may be NOT a pointer.
Apparently I cant put code in comments. Anyway this was in response to Charlies answer. By the way he is right and the method above is doable but is not the safest method. Below is a safer method.
you can produce a refmanger class with this code:
class refmanager{
private:
int count;
public:
refmanager():count(0){}
virtual ~refmanager() {}
void ref(refmanager* ptr)
{
ptr->count+=1;
}
void deref(refmanager* ptr)
{
ptr->count-=1;
if (ptr->count==0)
delete ptr;
}
};
The refmanager class can be inherited by classes which need to have their pointers reference managed.
The code below will now only compile when V and T are objects which contain the ref and deref methods with the correct format. In other words you are ensuring the code will not crash unexpectedly in the middle of running it.
template <class M, class K, class V> void mapinsert(M &map, K key, V value)
{
value->ref(value);
map.insert(pair<K, V>(key, value));
}
template <class T> void clearmap(T input)
{
input[1]->deref(input[1]);
input.clear();
}