set a member attribute in a "generic" way - c++

Is it possible to set a member attribute in a "generic" way?
I am still new to c++ and just dived into templates, if this is the way to go?
The class i have to use has around 20 string members to be filled from informix database and i could loop through an array with the field(=attribute) names.
Let's say i have a simple class
class Foo
{
public:
attr1
attr2
Foo() { };
~Foo();
}
and i could use it like that:
Foo foo;
string myattr = "attr1";
string myval = "val x1";
string myval = "val x2";
setattribute( foo, myattr, myval1 ); // pseudocode... possible somehow?
cout << foo.attr1; // prints "val x1"
setattribute( foo, myattr, myval2 ); // pseudocode... possible somehow?
cout << foo.attr1; // prints "val x2"
The method i call in the loop could look like this...
// its_ref : empty string reference
// row: ptr on the current db row = query result object
// colname: the db column = attribute
// ki: the object
void get_fd( ITString & its_ref, ITRow * row, ITString colname, ns4__SOAPKunde& ki ) {
ITConversions *c;
ITValue *v = row->Column( colname );
v->QueryInterface(ITConversionsIID, (void **) &c);
c->ConvertTo( its_ref );
// here is the place i want to use it :
setattribute( ki, colname, its_ref.Data() );
}

You can use member data pointers. These can be of any type- e.g.
struct x {
int y;
int z;
};
int main() {
int x::* res = &x::y;
}
However, if you want to start accessing them by identifier at runtime, you will have to build your own system from scratch.

The only option I can think of would be to store you attributes in a map of boost::any. With the assumption that you want your attributes to be of heterogeneous types.
The basic idea is to replace your attributes in Foo with map. So instead of having all your private attributes you would have a map that wraps them. The problem with C++ is that your attribute names don't exist after compiling the program (unlike other scripted languages like python). So there is no way to access an attribute variable from a string representing it's name without using some kind of data structure
removed old edit_

You could use a std::map.
The (base) class of 'ki' then has to implement setattribute like this:
// Member variable of MyClass
std::map<string, string> mProps;
void MyClass::setattribute( const char * name, const char * value )
{
mProps[name] = value;
}

Related

Save reference to void pointer in a vector during loop iteration

Guys I have a function like this (this is given and should not be modified).
void readData(int &ID, void*&data, bool &mybool) {
if(mybool)
{
std::string a = "bla";
std::string* ptrToString = &a;
data = ptrToString;
}
else
{
int b = 9;
int* ptrToint = &b;
data = ptrToint;
}
}
So I want to use this function in a loop and save the returned function parameters in a vector (for each iteration).
To do so, I wrote the following struct:
template<typename T>
struct dataStruct {
int id;
T** data; //I first has void** data, but would not be better to
// have the type? instead of converting myData back
// to void* ?
bool mybool;
};
my main.cpp then look like this:
int main()
{
void* myData = nullptr;
std::vector<dataStruct> vec; // this line also doesn't compile. it need the typename
bool bb = false;
for(int id = 1 ; id < 5; id++) {
if (id%2) { bb = true; }
readData(id, myData, bb); //after this line myData point to a string
vec.push_back(id, &myData<?>); //how can I set the template param to be the type myData point to?
}
}
Or is there a better way to do that without template? I used c++11 (I can't use c++14)
The function that you say cannot be modified, i.e. readData() is the one that should alert you!
It causes Undefined Behavior, since the pointers are set to local variables, which means that when the function terminates, then these pointers will be dangling pointers.
Let us leave aside the shenanigans of the readData function for now under the assumption that it was just for the sake of the example (and does not produce UB in your real use case).
You cannot directly store values with different (static) types in a std::vector. Notably, dataStruct<int> and dataStruct<std::string> are completely unrelated types, you cannot store them in the same vector as-is.
Your problem boils down to "I have data that is given to me in a type-unsafe manner and want to eventually get type-safe access to it". The solution to this is to create a data structure that your type-unsafe data is parsed into. For example, it seems that you inteded for your example data to have structure in the sense that there are pairs of int and std::string (note that your id%2 is not doing that because the else is missing and the bool is never set to false again, but I guess you wanted it to alternate).
So let's turn that bunch of void* into structured data:
std::pair<int, std::string> readPair(int pairIndex)
{
void* ptr;
std::pair<int, std::string> ret;
// Copying data here.
readData(2 * pairIndex + 1, ptr, false);
ret.first = *reinterpret_cast<int*>(ptr);
readData(2 * pairIndex + 2, ptr, true);
ret.second = *reinterpret_cast<std::string*>(ptr);
}
void main()
{
std::vector<std::pair<int, std::string>> parsedData;
parsedData.push_back(readPair(0));
parsedData.push_back(readPair(1));
}
Demo
(I removed the references from the readData() signature for brevity - you get the same effect by storing the temporary expressions in variables.)
Generally speaking: Whatever relation between id and the expected data type is should just be turned into the data structure - otherwise you can only reason about the type of your data entries when you know both the current ID and this relation, which is exactly something you should encapsulate in a data structure.
Your readData isn't a useful function. Any attempt at using what it produces gives undefined behavior.
Yes, it's possible to do roughly what you're asking for without a template. To do it meaningfully, you have a couple of choices. The "old school" way would be to store the data in a tagged union:
struct tagged_data {
enum { T_INT, T_STR } tag;
union {
int x;
char *y;
} data;
};
This lets you store either a string or an int, and you set the tag to tell you which one a particular tagged_data item contains. Then (crucially) when you store a string into it, you dynamically allocate the data it points at, so it will remain valid until you explicitly free the data.
Unfortunately, (at least if memory serves) C++11 doesn't support storing non-POD types in a union, so if you went this route, you'd have to use a char * as above, not an actual std::string.
One way to remove (most of) those limitations is to use an inheritance-based model:
class Data {
public:
virtual ~Data() { }
};
class StringData : public Data {
std::string content;
public:
StringData(std::string const &init) : content(init) {}
};
class IntData : public Data {
int content;
public:
IntData(std::string const &init) : content(init) {}
};
This is somewhat incomplete, but I think probably enough to give the general idea--you'd have an array (or vector) of pointers to the base class. To insert data, you'd create a StringData or IntData object (allocating it dynamically) and then store its address into the collection of Data *. When you need to get one back, you use dynamic_cast (among other things) to figure out which one it started as, and get back to that type safely. All somewhat ugly, but it does work.
Even with C++11, you can use a template-based solution. For example, Boost::variant, can do this job quite nicely. This will provide an overloaded constructor and value semantics, so you could do something like:
boost::variant<int, std::string> some_object("input string");
In other words, it's pretty what you'd get if you spent the time and effort necessary to finish the inheritance-based code outlined above--except that it's dramatically cleaner, since it gets rid of the requirement to store a pointer to the base class, use dynamic_cast to retrieve an object of the correct type, and so on. In short, it's the right solution to the problem (until/unless you can upgrade to a newer compiler, and use std::variant instead).
Apart from the problem in given code described in comments/replies.
I am trying to answer your question
vec.push_back(id, &myData<?>); //how can I set the template param to be the type myData point to?
Before that you need to modify vec definition as following
vector<dataStruct<void>> vec;
Now you can simple push element in vector
vec.push_back({id, &mydata, bb});
i have tried to modify your code so that it can work
#include<iostream>
#include<vector>
using namespace std;
template<typename T>
struct dataStruct
{
int id;
T** data;
bool mybool;
};
void readData(int &ID, void*& data, bool& mybool)
{
if (mybool)
{
data = new string("bla");
}
else
{
int b = 0;
data = &b;
}
}
int main ()
{
void* mydata = nullptr;
vector<dataStruct<void>> vec;
bool bb = false;
for (int id = 0; id < 5; id++)
{
if (id%2) bb = true;
readData(id, mydata, bb);
vec.push_back({id, &mydata, bb});
}
}

Auto return type of a function in c++

I have a problem that Im not able to solve. I have tried to find similar question here, but didnt find working solution for me.
My structure is:
class Base
{
unsigned int ID;
};
class Position: public Base
{
float x,y;
Position(float a, float b): x(a), y(b) {}
}
class Mass: public Base
{
float mass;
Mass(float a): mass(a) {}
}
I store pointers to all attributes in a map accesed with strings.
I would like to have a function, that can return any attribute from this list using names.
Structure and desired functionality should be like this:
std::map<string, Base*> attributes;
???? getAtt(string name)
{
return attributes[name];
}
Position pos(1,2);
Mass mass(25.6);
attributes.emplace("TEST_POSITION", &pos);
attributes.emplace("TEST_MASS") &mass);
cout << "Mass of this object is " <<getAtt("TEST_MASS").mass << endl;
cout << "X - Position of this object is " << getAtt("TEST_POSITION").x ;
PRINTS: Mass of this object is 25.6
X - Position of this object is 1
This function, addition of attributes and memory managment should be encapsuled in another class, but I think that wont be such problem after i get this thing solved.
So is there a way to do that? I was thinking about templates, but I dont understand them enough to make them work :( I was thinking about not storing all attributes in one array, but this way it is really easy.
Thanks for any suggestions :)
Your getAtt will return a Base*, like this:
Base* getAtt(const string& name)
{
...
}
But Base class doesn't provide a interface for all its derived class, so you can't just do
getAtt("TEST_MASS").mass
instead you have to do this:
dynamic_cast<Mass*>(getAtt("TEST_MASS"))->mass;
dynamic_cast<Position*>(getAtt("TEST_POSITION"))->x;
There are alternatives, for example you can use a tagged union, but that might be too complex for your problem.
By the way, [] operator of map will create a element if it doesn't exist, so you need to check getAtt isn't returning a nullptr.
The compiler cannot deduce the return type without you hinting it. You can use a template for that:
template <typename T>
T& getAtt(string name)
{
return dynamic_cast<T&>(*attributes.at(name));
}
Edit: use at instead of [], [] has the side-effect that it creates non-existing keys.
And then call it like this:
getAtt<Mass>("TEST_MASS").mass
getAtt<Position>("TEST_POSITION").x
However, this code would be nightmare to debug. Try to avoid generic attributes and use strong-typed variables, ie. instead of:
std::map<string, Base*> attributes;
attributes.emplace("mass", Mass(…));
attributes.emplace("position", Position(…));
use:
Mass mass;
Position position;
You can return a reference object that has a conversion operator to the type. If the conversion is implemented with a dynamic cast, the result will be NULL if an attempt is made to assign the object to something that it is not. Dynamic cast requires Base to have a virtual method (you could just add a virtual destructor).
class Base {
unsigned int ID;
protected:
virtual ~Base () {}
};
class Ref {
friend Ref getAtt (std::string name);
Base *ref_;
Ref (Base *p = 0) : ref_(p) {}
public:
template <typename D> operator D * () const {
return dynamic_cast<D *>(ref_);
}
};
Ref getAtt (std::string name) { return attributes[name]; }
This technique does not allow you to treat a Ref as any particular type. It allows you to assign it to something that it is allowed to become.
Mass *m = getAtt("TEST_MASS");
Position *p = getAtt("TEST_POSITION");
cout << "Mass of this object is " << m->mass << endl;
cout << "X - Position of this object is " << p->x ;
If the resulting pointer is NULL, it means either the item did not exist, or you are attempting to assign it to the wrong thing.
Position *p = getAtt("TEST_MASS");
assert(p == NULL);

Retrieve array name

I have written a function in c++ which receives a struct as a input. The struct object received has two arrays. I need to use both the arrays for different purposes. The array names have been created in a certain format. How to retrieve array names in a string.
struct INFO
{
float fADataLHS[3] = {1,2,3};
float fADataRHS[3] = {4,5,6};
Struct INFO has been defined where two arrays have been defined an initialized. The function useStruct uses both the function for different purposes.
void useStruct(struct *INFO)
{
--------;
--------;
}
int main()
{
struct INFO info;
useStruct(info);
}
I want a method in which I can retrieve the name of the array as for ex. fAdataLHS and store it to a string. The idea is to find the sub-string LHS and RHS from the string names and process then accordingly.
PS: I am quite new to c++.
I will go simple as you're a begginer to C++.
If you want to use both of arrays for different purposes, just doit. For instance:
void use_array_for_different_purposes(INFO *info)
{
// Purpose one, printing values using fADataLHS.
for (int i = 0; i < 3; i++) {cout << info->fADataLHS[i] << endl;}
// Purpose two, computing total sum using fADataRHS.
int acum;
for (int i = 0; i < 3; i++) {acum += info->fADataRHS[i];}
}
As you can see, you don't need to get the arrays names as strings values.
If I understand corectly, your use case is this: you have two (or more) names and each has a float array associated with it. You want to get the array by name and process the data.
Consider this code:
class INFO
{
std::map<std::string, std::vector<float>> vectors;
public:
INFO() : vectors{}
{
vectors["fADataLHS"] = { 1, 2, 3 };
vectors["fADataRHS"] = { 4, 5, 6 };
}
const std::vector<float>& operator[](const std::string& key) const // access vector by key
{
return vectors.at(key);
}
};
void useStruct(const INFO& info) // pass instance by const reference
{
std::cout << info["fADataLHS"][0] << "\n"; // access element 0 from the fADataLHS array
// get the entire array:
const auto& arr = info["fADataRHS"];
// this will throw a std::out_of_bounds
const auto& arr = info["non-existent-key"];
}
EDIT: A few other notes:
in C++ try not to use float - use double instead
if you need to alter the vector contents from client code, add a non-const version of the operator[]

Perform some operation on each of recursive structure's element, without adding methods to it in C++

The task: perform operation on each of recursive structure's element, without modifying it (the structure has only members and no methods except for constructor) inside Presenter::present(...) method (that makes use of private members of Presenter).
The problem: the structure does NOT have any methods except for constructor.
Example:
I have an structure:
struct Component{
std::vector<Component *> children;
Component * parent;
std::string ID;
std::string content;
Component(ID, content){...}
};
Then I have some code like:
Component * a, * b, * c1, * c2;
a = new Component("A", "a content");
b = new Component("B", "b content");
c1 = new Component("C1", "c1 content");
c2 = new Component("C2", "c2 content");
b->parent = a;
a->children.push_back(b);
c1->parent = b;
c2->parent = b;
b->children.push_back(c1);
b->children.push_back(c2);
I now want, having a pointer passed to my Presenter::present(...):
class Presenter{
private:
std::string somethingImportant; // = "sth";
...
public:
std::string present(Component * a){
... //on each component's children (and component itself):
//get ID and content then add something from this (Presenter)
//or modify the ID/content a bit.
//At the end, return the result (for all components together).
}
...
}
Output to std::string (or console, nvm) all ID-content pairs like:
A a content sth
B b content sth
C1 c1 content sth
C2 c2 content sth
It could be easily achieved by adding some recursivePresent(std::string &output) method to Component structure.
But I want to know if it's possible to do it without modifying Component structure (without adding any method to it)?
EDIT (made because of comments): Note that the output makes use of some Presenter's private/protected members/methods - I cannot assume that it will be just one "sth" like in an example.
I cannot find such solution, but I believe that somebody here can surprise me with some crazy idea ;)
Answer to comment: #firda can you explain it a bit? I'm not sure what do you mean.
My comment was: Why not having it (the recursivePresent helper) on Presenter?
class Presenter {
void presentRecursive(Component *c, std::ostream& out) {
out << c->ID << ' ' << c->content << std::endl;
for(auto p : c->children) presentRecursive(p, out);
}
public:
void present(Component *c) {
presentRecursive(c, std::cout);
}
};
At runtime, a C++ struct (or class) object does not know its structure, fields, layout or size. These are only known at compilation time.
If you add a new field long newfield; at the end of your struct Component, most routines in your code will stay the same (except those allocating such a structure, they are using its size).
You need to have some runtime meta-data describing the structure of your object.

C++ Class design - easily init / build objects

Using C++ I built a Class that has many setter functions, as well as various functions that may be called in a row during runtime.
So I end up with code that looks like:
A* a = new A();
a->setA();
a->setB();
a->setC();
...
a->doA();
a->doB();
Not, that this is bad, but I don't like typing "a->" over and over again.
So I rewrote my class definitions to look like:
class A{
public:
A();
virtual ~A();
A* setA();
A* setB();
A* setC();
A* doA();
A* doB();
// other functions
private:
// vars
};
So then I could init my class like: (method 1)
A* a = new A();
a->setA()->setB()->setC();
...
a->doA()->doB();
(which I prefer as it is easier to write)
To give a more precise implementation of this you can see my SDL Sprite C++ Class I wrote at http://ken-soft.com/?p=234
Everything seems to work just fine. However, I would be interested in any feedback to this approach.
I have noticed One problem. If i init My class like: (method 2)
A a = A();
a.setA()->setB()->setC();
...
a.doA()->doB();
Then I have various memory issues and sometimes things don't work as they should (You can see this by changing how i init all Sprite objects in main.cpp of my Sprite Demo).
Is that normal? Or should the behavior be the same?
Edit the setters are primarily to make my life easier in initialization. My main question is way method 1 and method 2 behave different for me?
Edit: Here's an example getter and setter:
Sprite* Sprite::setSpeed(int i) {
speed = i;
return this;
}
int Sprite::getSpeed() {
return speed;
}
One note unrelated to your question, the statement A a = A(); probably isn't doing what you expect. In C++, objects aren't reference types that default to null, so this statement is almost never correct. You probably want just A a;
A a creates a new instance of A, but the = A() part invokes A's copy constructor with a temporary default constructed A. If you had done just A a; it would have just created a new instance of A using the default constructor.
If you don't explicitly implement your own copy constructor for a class, the compiler will create one for you. The compiler created copy constructor will just make a carbon copy of the other object's data; this means that if you have any pointers, it won't copy the data pointed to.
So, essentially, that line is creating a new instance of A, then constructing another temporary instance of A with the default constructor, then copying the temporary A to the new A, then destructing the temporary A. If the temporary A is acquiring resources in it's constructor and de-allocating them in it's destructor, you could run into issues where your object is trying to use data that has already been deallocated, which is undefined behavior.
Take this code for example:
struct A {
A() {
myData = new int;
std::cout << "Allocated int at " << myData << std::endl;
}
~A() {
delete myData;
std::cout << "Deallocated int at " << myData << std::endl;
}
int* myData;
};
A a = A();
cout << "a.myData points to " << a.myData << std::endl;
The output will look something like:
Allocated int at 0x9FB7128
Deallocated int at 0x9FB7128
a.myData points to 0x9FB7128
As you can see, a.myData is pointing to an address that has already been deallocated. If you attempt to use the data it points to, you could be accessing completely invalid data, or even the data of some other object that took it's place in memory. And then once your a goes out of scope, it will attempt to delete the data a second time, which will cause more problems.
What you have implemented there is called fluent interface. I have mostly encountered them in scripting languages, but there is no reason you can't use in C++.
If you really, really hate calling lots of set functions, one after the other, then you may enjoy the following code, For most people, this is way overkill for the 'problem' solved.
This code demonstrates how to create a set function that can accept set classes of any number in any order.
#include "stdafx.h"
#include <stdarg.h>
// Base class for all setter classes
class cSetterBase
{
public:
// the type of setter
int myType;
// a union capable of storing any kind of data that will be required
union data_t {
int i;
float f;
double d;
} myValue;
cSetterBase( int t ) : myType( t ) {}
};
// Base class for float valued setter functions
class cSetterFloatBase : public cSetterBase
{
public:
cSetterFloatBase( int t, float v ) :
cSetterBase( t )
{ myValue.f = v; }
};
// A couple of sample setter classes with float values
class cSetterA : public cSetterFloatBase
{
public:
cSetterA( float v ) :
cSetterFloatBase( 1, v )
{}
};
// A couple of sample setter classes with float values
class cSetterB : public cSetterFloatBase
{
public:
cSetterB( float v ) :
cSetterFloatBase( 2, v )
{}
};
// this is the class that actually does something useful
class cUseful
{
public:
// set attributes using any number of setter classes of any kind
void Set( int count, ... );
// the attributes to be set
float A, B;
};
// set attributes using any setter classes
void cUseful::Set( int count, ... )
{
va_list vl;
va_start( vl, count );
for( int kv=0; kv < count; kv++ ) {
cSetterBase s = va_arg( vl, cSetterBase );
cSetterBase * ps = &s;
switch( ps->myType ) {
case 1:
A = ((cSetterA*)ps)->myValue.f; break;
case 2:
B = ((cSetterB*)ps)->myValue.f; break;
}
}
va_end(vl);
}
int _tmain(int argc, _TCHAR* argv[])
{
cUseful U;
U.Set( 2, cSetterB( 47.5 ), cSetterA( 23 ) );
printf("A = %f B = %f\n",U.A, U.B );
return 0;
}
You may consider the ConstrOpt paradigm. I first heard about this when reading the XML-RPC C/C++ lib documentation here: http://xmlrpc-c.sourceforge.net/doc/libxmlrpc++.html#constropt
Basically the idea is similar to yours, but the "ConstrOpt" paradigm uses a subclass of the one you want to instantiate. This subclass is then instantiated on the stack with default options and then the relevant parameters are set with the "reference-chain" in the same way as you do.
The constructor of the real class then uses the constrOpt class as the only constructor parameter.
This is not the most efficient solution, but can help to get a clear and safe API design.