I need to evaluate a string so i can assign a value to a class variable :
Class :
class DATACLASS {
public:
double variable1, variable2, variable3;
};
The void init() :
void init()
{
DATACLASS *d = new DATACLASS;
std::string ssList[3] = {"variable1",
"variable2",
"variable3"};
for(unsigned i = 0; i < 3; ++i)
{
std::stringstream ss;
ss << ssList[i];
//ss.str().c_str() correspond to "variable1", "variable2", "variable3"
mxArray *array_ptr = mexGetVariable("base", ss.str().c_str());
double pr = (double)mxGetPr(array_ptr)[0];
// How to make the same thing here?
// I would like to have something that would evaluate
// data->ssList[i] = pr;
// or more precisely
// data->variable1 = pr;
// but from the ss string like below (but this doesn't work)
data->ss.str().c_str() = pr;
}
I get this kind of error when trying to do it this way :
error C2039: 'ss' : is not a member of 'DATACLASS'
That is not valid C++. What the compiler thinks that you are trying to do is access a member of an instance of DATACLASS called ss and call some methods on it.
What you are trying to do can be done in reflection, which is not supported in C++. You can half-ass it by using some form of pseudo-reflection model using templates.
Are you only reading doubles? You could use pointers to data members for this.
std::map<std::string, double DATACLASS::*> aMembers;
aMembers["variable1"] = &DATACLASS::variable1;
aMembers["variable2"] = &DATACLASS::variable2;
aMembers["variable3"] = &DATACLASS::variable3;
DATACLASS dc;
std::string sData = "variable1";
dc.*aMembers[sData] = 10;
In a full solution you would of course have to check that aMembers[sData] exists first. If you need to support multiple data types, you would need to use templates and write some support classes. It should be doable, though.
The closest you'll reasonably come without a huge amount of effort is something like the following. You could abstract away some things using macros, functions, containers, templates, pointers/references, etc., but this is the basic gist. I wouldn't suggest doing this and committing the time to it unless you have a compelling reason. What is your end goal?
class DATACLASS {
public:
double variable1, variable2, variable3;
};
void init()
{
DATACLASS *d = new DATACLASS;
std::string ssList[3] = {"variable1",
"variable2",
"variable3"};
for(unsigned i = 0; i < 3; ++i)
{
std::stringstream ss;
ss << ssList[i];
//ss.str().c_str() correspond to "variable1", "variable2", "variable3"
mxArray *array_ptr = mexGetVariable("base", ss.str().c_str());
double pr = (double)mxGetPr(array_ptr)[0];
if(ss.str() == "variable1")
data->variable1 = pr;
else if(ss.str() == "variable2")
data->variable2 = pr;
else if(ss.str() == "variable3")
data->variable3 = pr;
}
}
Related
I ran into a little problem programming something, I've looked around but I didn't seem to find out the answer.
I'll spare you useless code.
Here are the declarations:
struct one {
std::string string1, string2;
bool boolean;
};
struct two {
std::string string3, string4;
bool boolean;
};
void function(uint first_parameter, one **first, two **second);
And here is what the main looks like:
int main()
{
one *passes;
two *users;
//...
passes = new one[size_one]();
users = new two[size_two]();
//Filling the arrays...
std::thread t[PARTS];
for (int start = 0; start < PARTS; start++)
t[start] = std::thread(function, first_parameter, &passes, &users);
for (int i = 0; i < PARTS; i++)
t[i].join();
}
Whenever I try to access an element of one of my structures (allocated on the free store) in my thread function, (I typically would access it like so: (*first)[0].string1[0]) I do not get the string1 I normally can access in main. Aren't the std::strings located in the free store?
check your function to have valid types of parameters.
this example bellow works nice.
#include <iostream>
typedef struct _one
{
std::string first_str;
std::string second_str;
bool check;
} one;
void do_something(one** passes)
{
one* original = *passes;
one first = original[0];
std::cout << first.first_str; // -> hello
// the same
std::cout << (*passes)[0].first_str;
}
int main()
{
one* passes = nullptr;
passes = new one[10];
passes[0].first_str = "hello";
do_something(&passes);
}
Consider the following function (myfct). When this function returns, data points to either uint16_t, float_t or double_t.
In main(), this function is called in a for loop. I want for each iteration to save "data" in a std::vector with the type it points to. How can I do that? Thanks in advance.
PS: the container must not necessarily be a vector, it can be anything else, I just want to save "data" without loosing the pointer type information.
void myfct(void*&data, int id) {
if(id==1) {
uint16_t* ptr = ...;
data = ptr;
}
else if(id==2) {
float_t* ptr = ...;
data = ptr;
}
else if(id==3) {
double_t* ptr = ...;
data = ptr;
}
}
int main()
{
void* dataPtr = nullptr;
vector<?> myVec; //how should I template my vector? which typename?
for(int i = 0, i<5, i++)
{
myfct(dataPtr , i); //note that dataPtr is passed by reference
myVec.push_back(dataPtr ); //here dataPtr point to either uint16_t,
//float_t or double_t. I want to save it with the type it point to.
}
}
If you don't have access to std::variant, the way to do it would be the following:
class custom_type {
int id;
union data_holder
{
uint16_t i;
float_t f;
double_t d;
} data;
}
Now, you can have a vector<custom_type>, and if you want to work with a data point, you can do
custom_type c = myvec.back();
if( c.id == 1 ) {
uint16_t val = c.data.i;
// Process val in a uint way
} else if( c.id == 2 ) {
float_t val = c.data.f;
// Process val in a float way
} ...
You can learn more about unions here. Now, in order to make your code handle the data types easily (So you don't have to write the similar "process val in an X way" over and over again), you can use templates. For example,
template <typename T>
T calculate(T val) {
// Do stuff with val
return computed_val;
}
And now,
custom_type c = myvec.back();
if( c.id == 1 ) {
uint16_t val = calculate<uint16_t>(c.data.i);
cout << val;
} else if( c.id == 2 ) {
float_t val = calculate<float_t>(c.data.f);
cout << val;
} ...
What you want is polymorphism, e.g., a base class (can be an interface/abc) and then derived classes, which implement some typeof functor. I can give an example if you wish to, but I think it would be a lot more valuable for you to learn how to do it yourself.
Another way is to use boost::variant or boost::any.
I have a strange issue. I allocate char[] values in struct array, but they get lost:
------- The struct is this one :
typedef struct _Settings
{
const char* str;
uint val;
}Settings;
------- I create it like this :
int nn=10;
settings = new Settings[nn];
for (int i = 0; i < nn; i++) {
string strr = "thisOneIs";
strr.append(std::to_string(i));
settings[i].str = strr.c_str();
string teststr = settings[i].str; //// (1)
settings[i].val = i + 1;
}
..... at (1), I get the correct values.
But if I then call this (same place, right after the code above), the settings[i].str is empty:
for (int i = 0; i < nn; i++) {
string teststr = settings[i].str; ///// (2)
std::cout << settings[i].str << "=" << settings[i].val << "\n";
}
... at (2), I get empty.
Does anyone have a clue why? Thanks!
The line at (1) is a problem because you are storing a pointer to some memory that is not valid when the loop ends.
string strr = "thisOneIs"; // A temporary object in the loop.
strr.append(std::to_string(i));
settings[i].str = strr.c_str(); // Pointer that won't be valid when the loop ends.
If you learning about low level language features, it's ok to experiment with using char* and raw memory. If you are trying to get a working program, just use std::string.
Also simplify the definition of Settings. You don't need all the typedef non-sense in C++.
struct Settings
{
std::string str;
uint val;
};
I have to build a dynamic sql query. To proper execute it I have to do it in 3 steps:
Prepare statement
Bind Parameters with functions: bindString(string value, int index); bindInt(int value, int index);
Execute it
Because of the fact, that this query is build dynamically I have to store somewhere proper values for given index.
For example:
SELECT * FROM Table WHERE A = ? AND E = '?';
SELECT * FROM Table WHERE A = ? AND B = ? AND E = '?';
During building query I have to store somewhere that:
In the first case:
index 0 is for int A,
index 1 is for string E
In the second case:
index 0 is for int A
index 1 is for int B
index 2 is for string E
My best idea is to create two maps: < int, string >, < int, int > and during creating query set in first place indexes and in second place values and then creating two loops, one for strings, the second one for integers and binding parameters in them and it works fine.
However I wonder if is it possible to do everything in one loop using succeeding indexes and in type safety way.
Thank You.
I would consider creating a class to wrap SQL parameters.
In fact I would create an abstract class like that :
SQLParameterBase
{
std::string toString() = 0;
void print()
{
std::cout << toString();
}
}
And then a template class :
template<class ParamType>
SQLParameter : public SQLParameterBase
{
private:
ParamType value;
public:
std::string toString()
{
// You can use std::ostringstream to convert to string,
// or create another class (derivated from SQLParameterBase) with very specific values
}
}
And you could use it like that :
SQLParameterBase * params[10];
maps[0] = new SQLParameter<int>();
Hope that will help
Actually it is modified AMDG solution. Thanks to him!
class SQLParam {
public:
virtual ~SqlParam(){}
void bind(DatabaseHandler &db, int index) = 0;
};
class SQLParamInt {
private:
int value;
public:
SqlParamInt(int p_value) : value(p_value) {
}
~SqlParamInt() {}
int bind(DatabaseHandler &db, int index) {
return db.bindInt(value, index);
}
};
class SQLParamString {
private:
string value;
public:
SqlParamString(std::string p_value) : value(p_value) {
}
~SqlParamString() {}
int bind(DatabaseHandler &db, int index) {
return db.bindString(value, index);
}
};
typedef std::vector<std::unique_ptr<SqlParam>> SqlParamsContainer;
typedef std::unique_ptr<SqlParamInt> SqlParamIntPtr;
typedef std::unique_ptr<SqlParamString> SqlParamStringPtr;
In my function, building query:
int buildQuery(RequestHandler &request) {
SqlParamsContainer params;
stringstream query << "SELECT * FROM Table WHERE A = ?";
params.push_back(SqlParamIntPtr(new SqlParamInt(request.A())));
if(request.has_B()) {
params.push_back(SqlParamIntPtr(new SqlParamInt(request.B())));
query << " AND B = ?";
}
if(request.has_C()) {
params.push_back(SqlParamStringPtr(new SqlParamString(request.C())));
query << " AND C = ?";
}
query << ";";
db.prepare(query.str());
for(int i = 0; i < v_container.size(); i++)
v_container.at(i)->bind(db,i);
}
There is Boost::Any while it is more general than what you ask for and does not prevent the user from storing unsupported types you do not need to worry about creating the according subclasses.
If you want to return results as well from your DB Boost::Any might be the answer as well.
I suggest limiting the types in your bind function rather than in the storage. If you work with a variadic bind function this is necessary anyways.
Hey basically Im trying to store a "solution" and create a vector of these. The problem I'm having is with initialization. Heres my class for reference
class Solution
{
private:
// boost::thread m_Thread;
int itt_found;
int dim;
pfn_fitness f;
double value;
std::vector<double> x;
public:
Solution(size_t size, int funcNo) : itt_found(0), x(size, 0.0), value(0.0), dim(30), f(Eval_Functions[funcNo])
{
for (int i = 1; i < (int) size; i++) {
x[i] = ((double)rand()/((double)RAND_MAX))*maxs[funcNo];
}
}
Solution() : itt_found(0), x(31, 0.0), value(0.0), dim(30), f(Eval_Functions[1])
{
for (int i = 1; i < 31; i++) {
x[i] = ((double)rand()/((double)RAND_MAX))*maxs[1];
}
}
Solution operator= (Solution S)
{
x = S.GetX();
itt_found = S.GetIttFound();
dim = S.GetDim();
f = S.GetFunc();
value = S.GetValue();
return *this;
}
void start()
{
value = f (dim, x);
}
/* plus additional getter/setter methods*/
}
Solution S(30, 1) or Solution(2, 5) work and initalizes everything, but I need X of these solution objects. std::vector<Solution> Parents(X) will create X solutions with the default constructor and i want to construct using the (int, int) constructor. Is there any easy(one liner?) way to do this? Or would i have to do something like:
size_t numparents = 10;
vector<Solution> Parents;
Parents.reserve(numparents);
for (int i = 0; i<(int)numparents; i++) {
Solution S(31, 0);
Parents.push_back(S);
}
the example I gave as a comment uses copy constructor to create new objects.
You can do the following:
// override copy constructor
Solution(const Solution &solution) {
... copy from another solution
}
however be careful, as you no longer going to have exact object copy/construct if you introduce random generation in your copy constructor, i.e. Solution y = x; y != x
your best solution is something like you already have in my opinion
I have used the Boost assignment library for tasks like this. You may find it useful....