Class with template member variable and functions - c++

I'm trying to create something like this:
// The code doesn't work, it should just be a pseudo to help understand what i'm trying to create
template <typename Variable>
class Address
{
unsigned int A_Address;
Variable A_Type;
void Set(A_Type value)
{
*((A_Type*)A_Address) = value;
}
A_Type Get()
{
return *((A_Type*)A_Address);
}
};
Address address_1 = new Address<float/*type*/>(0x00000000/*address in memory*/);
address_1.Set(30.0f);
float value_1 = address_1.Get();
Address address_2 = new Address<int/*type*/>(0x00000000/*address in memory*/);
address_2.Set(10);
int value_2 = address_2.Get();
So i want to be able to define objects like Address obj_1, obj_2; and then Initialize them later with a type and an address. Then the Get() method should return it's current value in memory and the Set() method should set that value in memory. I couldn't figure out how to not do Address<float> obj_1; and instead using Address obj_1; and initializing it later. Hope you understood what i'm trying to do and could let me know if it's possible and if so maybe help me out or point me in the right direction.
Thanks in advance!

I'm not really dealing with your address mangling but what you want can be done that way :
struct Address
{
Address(unsigned int addr)
: A_Address(addr)
{}
unsigned int A_Address;
template <typename T>
void Set(T value)
{
*((T*)A_Address) = value;
}
template <typename T>
T Get()
{
return *((T*)A_Address);
}
};
And you can use it that way
Address address(0x00000000); //won't work because of virtual addressing
address.Set<float>(10.0F);
std::cout << address.Get<float>();
address.Set<double>(99.0);
std::cout << address.Get<double>();
Be careful when you handle addresses that way, very error-prone. Have a look over there:
Pass a hex address to a Pointer Variable

Related

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.

Store the template that the class was initialized with

Im trying to figure out how to store my template, ill write a example:
class cDebugInfo
{
private:
DWORD * address;
string name;
template Type;
public:
Type GetFormattedValue()
{
return *(Type*)address;
}
cDebugInfo(){}
template <class T>
cDebugInfo(DWORD Address, string Name){
address = Address;
name = Name;
Type = T;
}
};
My goal, is to be able to add a item to my array:
std::vector<cDebugInfo>DebugItems;
template <class T>
void AddItem(std::string name, DWORD Address)
{
DebugItems.push_back(cDebugInfo(Address, name));
}
cDebugInfo* GetItemByNameP(std::string name)
{
for (int i = 0; i < DebugItems.size(); i++)
{
if (DebugItems[i].name == name)
{
return &DebugItems[i];
}
}
}
So i add the items to my array like this:
AddItem<int>(0x1337, "Test");
AddItem<string>(0x1337, "Test2");
And Therefore being able to call:
GetItemByName("Test")->GetFormattedValue();
And that should return the value in INT read form the given address since the template passed when i add the item, is a int. And ofcourse, the following should return the value stored in the address pointed by my pointer as a string:
GetItemByName("Test2")->GetFormattedValue();
I need it to "remember" what template was passed on to the class.
NOTE: Everything else works fine when i use GetItemByName with a template, but the thing is i dont know what template it is when i get them, only when i add them.
Thank you.
What you are asking for is not possible because every expression in C++ must have a known type at compile time. Consider this:
auto value = GetItemByName("BestItem")->GetFormattedValue();
GetItemByName(...) gives me a cDebugInfo*, but what does GetFormattedValue() give me? This must be the same type for every cDebugInfo* so that the above expression can be valid, so the type cannot withheld until runtime. So the general solution is impossible.
However, you can add specific solutions based on what it is you want to do. Let's say we just want to be able to print the formatted value. We can do that:
class cDebugInfo {
std::function<void()> printer; // type-erased functor
...
public:
template <class T>
cDebugInfo(DWORD Address, string Name){
address = Address;
name = Name;
printer = [this]{
std::cout << "Value as " << typeid(T).name() << ": "
<< *reinterpret_cast<T*>(address) << '\n';
};
}
};
This approach is called "type erasure". In this case, the lambda "stores" the type T, but the class itself just needs to know that it's a nullary function that returns void. We can expose that via:
void printValue() { printer(); }
So that:
GetItemByValue("BestItem")->printValue();
will print the value correctly based on the type it was constructed with.

Setting data members with generic setter

I'm trying to implement a superclass in c++ that would implement one method:
-void setValueForKey(void *value, string key);
all this method would have to do is to set the value of a property associated with a given key to the new value.
This would be easy in a language that implements introspection mechanisms; as far as I know C++ doesn't.
In order to accomplish this I created another method:
void registerKeyForProperty(void *propertyPtr, string key);
all this method does is it stores in and internal map a pointer to a property associated with a given key, so all my subclasses would call this for every property they declare and I would have a way of setting values for properties without necessity to use the setters.(That's what I need!) (I explain why at the end of the post...)
for this second function I have the following implementation:
void registerKeyForProperty(void *propertyPtr, string key){
_keysDictionary->insert(pair<string,void*>(key,property));
}
where _keysDictionary is a stl map.
for the first one I have the following implementation:
void ConstructableObject::setValueForKey(void* value, string key) {
map<string,void *>::iterator it=_keysDictionary->find(key);
if(it==_keysDictionary->end()){return;}//just return if there is nothing for that key
void *property=it->second;
(*property)=value;
}
the problem is the last line is not legal C++ because ofcourse I cannot just deference that void*.
My questions are:
Is there any other way of implementing the desired functionality?
Is there a "legal" way of doing this the way I am doing it? (I cannot simply use a reinterpret_cast cause I don't know what to cast to...)
Why this:
I need to parse and xml file that has some information about some objects. I'll be using TinyXML and therefore I'll have the atribute names for the objects and their values. That would be how I would like to use it:
MyClass obj();//the constructor would call setValueForKey(...,...) for every property so all are now registered
for every attribute{
obj.setValueForKey(attribute.value,attribute.name);
}
//all properties should be set now
If the key exists, why not simply do
_keysDictionary[key] = value;
Or if you want to use the iterator
it->second = value;
It could be done with using of the type awareness techniques and for example The Memento Pattern is one of choices. The following code could be extended with the some macro stuff that generating the unique keys based on the attribute pointer signature:
class introspection
{
public:
template <typename Class, typename Member>
void registerKey(std::string key, Member Class::*memberPointee, Class* classPointee)
{
typedef member_setter<Class, Member> hold_member_pointer;
base_setter* setter = new hold_member_pointer(memberPointee, classPointee);
keys.insert(std::make_pair(key, setter));
}
template <typename Value>
void setValue(std::string key, Value value)
{
if ( keys.count(key) > 0 )
{
keys[key]->set(value);
}
else
{
throw std::logic_error("no such key");
}
}
private:
struct base_setter
{
virtual void set(boost::any value) = 0;
}; // struct base_setter
template <typename Class, typename Member>
struct member_setter : base_setter
{
member_setter(Member Class::*memberPointee, Class* classPointee)
: memberPointee(memberPointee)
, classPointee(classPointee) {}
void set(boost::any value) override
{
Member newValue = boost::any_cast<Member>(value);
classPointee->*memberPointee = newValue;
}
Member Class::*memberPointee;
Class* classPointee;
}; // struct member_setter
std::map<std::string, base_setter*> keys;
}; // class introspection
struct Data
{
int value;
}; // struct Data
int main()
{
introspection i;
Data d;
d.value = 100;
i.registerKey("value", &Data::value, &d);
i.setValue("value", 200); // OK
i.setValue("value", "not valid"); // bad_any_cast
}
The one thing that could be (not so easily) improved here is provide the compile-time type check for setValue, instead of runtime any_cast casting.
Make setValueForKey be a templated function instead of a function that accepts a void pointer. That way, you can know about the type information of the property long enough to create a templated setter
class BaseSetter
{
public:
virtual void set(void* inValue) = 0;
}
template <typename T>
class SpecializedSetter
{
public:
SpecializedSetter(T* inMyValue)
: mValue(inValue)
{ }
virtual void set(void* inValue)
{
*mValue = *reinterpret_cast<T*>(inValue);
}
private:
T* mValue;
}
template <typename T>
void registerKeyForProperty(T* inValue, string inKey)
{
registerSetterForProperty(new SpecificSetter<T>(inValue), inKey);
}
This, however, assumes inValue is a pointer to the same type of data as the value on the class. To make that safe, consider boost::any or defining some other type which contains the type information from the XML file and using that rather than void*

How to save type information of template vector

I am trying to implement a class for serialization (XML for now). The idea is that any derived class can registers its members with the base class and base can write the members in form of XML.
The code looks something like this
class IXMLINF
{
protected:
struct INFObj
{
union MemPtr
{
int* piMem;
char* pstrMem;
IXMLINF* pINFMem;
}
MemPtr memObj;
};
vec<INFObj*> m_INFObjVec;
void addMemToINF(int* piMem)
{
INFObj* pObj = new INFObj;
pObj->memObj.piMem = piMem;
m_INFObjVec.append(pObj);
}
void addMemToINF(char* pstrMem);
void addMemToINF(IXMLINF* pINFMem);
void writeToXML()
{
for_each_element_in_m_INFObjVec
{
//if int or char process to XML
//else if IXMINF call its writeToXML
}
}
}
So far so good . However I also want to to be able to write vectors of types to XML. For int and char* it is easy but how to do it for vectors of IXMLINF derived class in a generic way (vec is a different type from vec)
One possible way might be
<class T>void addMemToINF(vec<T*>* pXMem)
{
//T is a class derived from IXMLINF
void* pvMem = (void*)pXMem
//Somehow store type of T
Type = T
}
void writeToXML()
{
....
vec<Type*>* pVec = (vec<Type*>*)pvMem ;
}
I will appreciate any suggestions on how to store Type informatio (Type = T step) or any alternate method for doing what I want to do.
FWIW this answer (by #Phillip) to a related question also answers this question with a little bit of tweaking . If anybody wants I can put the soln.

Is it possible to take a type as an argument in a function?

I'm trying to write a function for a database class that is basically just a wrapper around a hash_map of objects (say shapes) indexed by ID numbers that will look up an ID and cast it to the appropriate pointer type.
e.g. I'd like to be able to do something like this:
Circle* shapeToLookup = NULL;
int idNum = 12;
database.lookup(idNum, circleToLookup);
if(circleToLookup != NULL)
{
// Do stuff with the circle.
}
and have the database know the type of its argument. Is there a way to do this without either overloading the function (lookup(int, Circle*), lookup(int, Rect*), ad nauseum)? Can you declare a function like lookup(int, Shape*) and have it know which type it's given?
Thanks!
template <T>
Database::lookup(int idNum, T TobjectToLookup)
{
// inside here, T is the type of the object passed in/
}
You can do it with a template.
Edit: new implementation based on the extra information. If mymap is a std::map<int, Shape*>:
template <typename T>
void lookup(int idNum, T* &ptr) {
auto it = mymap.find(idNum);
if (it == mymap.end()) {
ptr = 0;
} else {
ptr = dynamic_cast<T*>(*it); // Shape must have a virtual member function
}
}
Or you might prefer:
template <typename T>
T* lookup(int idNum) {
auto it = mymap.find(idNum);
if (it == mymap.end()) {
return 0;
}
return dynamic_cast<T*>(*it);
}
Then call it like Circle *circle = database.lookup<Circle>(123);
Obviously polymorphic containers are a whole heap of fun in themselves, but I'll assume you have that sorted. There may well be a shared_ptr in there somewhere that I've left out.
Old implementation when I thought the DB might store copies of POD:
template <typename T>
void lookup(int idNum, T* &ptr) {
void *theresult = // something based on idNum
// some check needed here that theresult really is the right type.
// how you do this depends on the database, but suppose that
// the database gives us some integer "type" which indicates the type
if (type != type_constant<T>::value) {
ptr = 0;
} else {
ptr = static_cast<T*>(theresult);
}
}
type_constant is an example of "type traits", you implement it like:
template <typename T>
struct type_constant {};
template <>
struct type_constant<Circle> {
static const int value = 1;
};
template <>
struct type_constant<Rectangle> {
static const int value = 2;
};
// etc...
Others have explained how to pass a type to a function (by using function templates). I'd like to give another point of view:
It might be even better to introduce a new virtual function on Shape and then move the Do stuff with the Circle part into the reimplementation of that virtual function in the Cricle class.
That way, you remove the need to know the type. You just fetch a Shape object from your database and then call a doStuff() function - and it does the right thing depending on the actual type of the Shape. A good use case for a virtual function. :-)
Of course, this might be more or less simple, depending on what Do stuff actually does.