I’m in need of some help and guidance on the design of my code. I want to run tests with multiple variables set to multiple values, without creating insane amounts of nested loops. I got a struct which holds various variables like this (only three integers as an example, but the real deal will hold a lot more, including booleans, doubles etc):
struct VarHolder
{
int a;
int b;
int c;
// etc..
// etc..
};
The struct get passed into a test function.
bool TestFunction(const VarHolder& _varholder)
{
// ...
}
I want to run the test for all variables ranging for a their set range, all combinations of the variables. One way is to create a loop for each variable:
for (int a = 0; a < 100; a++)
{
for (int b = 10; b < 90; b++)
{
for (int c = 5; c < 65; c++)
{
//...
//...
//set variables
VarHolder my_varholder(a, b, c /*, ...*/);
TestFunction(my_varholder);
}
}
}
But this seems inefficient and gets unreadable fast as the amount of variables gets bigger. What is an elegant way to achieve this? One crux is that the variables will change in the future, removing some, adding new one’s etc. so some solution without rewriting loops for each variable as they change is preferable.
With range-v3, you might use cartesian_product view:
auto as = ranges::view::ints(0, 100);
auto bs = ranges::view::ints(10, 90);
auto cs = ranges::view::ints(5, 65);
// ...
// might be other thing that `int`
for (const auto& t : ranges::view::cartesian_product(as, bs, cs /*, ...*/))
{
std::apply(
[](const auto&... args) {
VarHolder my_varHolder{args...};
Test(my_varHolder);
},
t);
}
Related
I have a structure that contains x amount of integers, It is required that every last one of them be non-zero. Here's my structure:
struct thingy_t{
int a, b, c /* and so on */;
bool init();
};
Over time I will be adding many other members to the structure, which makes it an issue if I forget to check if it's non-zero. That's why I wanted to automate it for every member.
In my init function, it attempts to get values for the members, and return false if any of them are 0.
So far I have this:
bool thingy_t::init(){
a = GetValue(/* blah blah */); // Will return 0 if it can't find anything
b = GetValue(/* other blah */);
/* and so on */
// Check if any value is zero
for(int* i = (int*)this
; i < (int*)((char*)this + sizeof(interfaces_t))
; i++){
if(!*i) return false;
}
return true;
}
I am looking for a better way of doing this that would be more readable and more memory safe, as I am playing with fire(pointers) in a way they probably aren't intended.
Also, sorry for the for loop, I tried to make it more readable by wrapping it, but I probably made it worse.
There isn't a natural way to iterate over the struct and check for certain values of the members you have, so the better option for you, in my opinion, should be either make a better design for your task or make sure that you check for incorrect values on each access to that struct.
I'd simple implement the type to contain an array of int or (possibly better) a standard container.
If the number of values is specified at compile time ....
struct thingy_t
{
int x[number];
bool all_non_zero() const;
};
bool thingy_t::all_non_zero() const
{
for (int i = 0; i < number; ++i)
if (!number[i]) return false;
return true;
}
If the number is not specified at compile time, I'd use a standard container
struct thingy_t
{
std::vector<int> x;
thingy_t(std::size_t size) : x(size) {};
bool all_non_zero() const;
};
bool thingy_t::all_non_zero() const
{
for (std::vector<int>::const_iterator it = x.begin(), end = x.end();
it != end number; ++it)
if (!(*it)) return false;
return true;
}
The above works for all versions of C++, but may be simplified in C++11 or later.
bool thingy_t::all_non_zero() const
{
for (const auto &element : x)
if (!element) return false;
return true;
}
Naturally, you will need other functions to actually store values in the array or vector.
The code won't change if the number of integers changes. You will need to somehow track separately the meaning of each element.
I solved my own question while enjoying a nice breakfast.
Here's how I solved it:
struct thingy_t{
union{
struct{
int a, b, c;
}
int arr[3];
}
}
That way I can access variables via. their name and also their index in an array so I can check if each value is non-zero easier (creds: James Root for the array inspiration)
I have a class like this:
class Wall
{
private :
Quad faces[6];
};
I have the constructor like this :
Wall::Wall(Quad f[], const float &mass, Vector3 center)
I want to initialize faces to be f(or copy f to faces),Quad is struct that doesn't have a default constructor.
Now I solved the problem by using faces{f[0],f[1],f[2],f[3],f[4],f[5]} in the initializer list but this requires c++11 which I'm afraid some of my friends don't have it, and I need to pass my code to them.
There are many similar questions but all of them seem to not have solutions other than switching to vector or using some complicated code which I don't want, as you can understand from the classes' name, a Wall doesn't need a vector(it only has 6 faces so why a vector).
Is this really hopeless ? isn't there any way ?
PS
Whether in the constructor body or in the initializer list, it doesn't matter.
changing to dynamic arrays(Quad *) doesn't matter either but keeping with static arrays is preferable.
Several options. The easiest is probably to subclass Quad with something that has a default constructor:
class Wall {
public:
Wall(Quad f[], ...) {
for (int i = 0; i < 6; ++i) faces[i] = f[i];
}
private:
class MyQuad : public Quad {
MyQuad() : Quad(...) {}
}
MyQuad faces[6];
};
Another option is to use placement new - note that the code below doesn't work out of the box since it is not doing proper alignment/padding and dealing with some aliasing issues, which are left as an exercise to the reader. It should give you a starting point though.
class Wall {
public:
Wall(Quad f[], ...) {
for (int i = 0; i < 6; i++) {
// TODO: take padding into account
new (&faces_data + sizeof(Quad) * i) Quad(f[i]);
}
}
~Wall() {
for (int i = 0; i < 6; i++) {
face(i).~Quad();
}
}
Quad& face(int idx) {
// TODO: take padding into account
return (reinterpret_cast<Quad*>(faces_data))[idx];
}
private:
// TODO: force proper alignment and take padding into account
char faces_data[sizeof(Quad) * 6];
};
I have a class Itch that is a member of the class Scratch. I want to do some computations in the Scratch constructor and pass the result of these computations to instantiate the Itch object. My best guess in doing this is below, but this returns garbage:
#include <iostream>
class Itch {
public:
int N;
Itch(int n) {N = n;}
};
class Scratch {
private:
int N;
public:
Itch it;
Scratch(int n);
};
Scratch::Scratch(int n) : it(N) // here is where I want to use new data
{
// do some silly things
int temp = 5;
temp += n + 45;
N = temp - 1;
}
int main() {
int n = 1;
Scratch sc(n);
std::cout << sc.it.N << "\n";
}
Is there a standard way to do this?
The things in the initializer list happen before the things in the constructor code. Therefore, you cannot affect anything in the initializer list with the code in the constructor. You have a few options.
A reasonable approach would be to have an Itch * member rather than an Itch, and initialize it when it's ready, e.g.:
class Scratch {
...
Itch *it;
...
};
Scratch::Scratch(int n) : it(NULL)
{
// do some silly things
int temp = 5;
temp += n + 45;
N = temp - 1;
it = new Itch(N); // <- now you have enough info to instantiate an Itch
}
And you'll have to remember to clean up in the destructor unless you use an auto_ptr:
Scratch::~Scratch () {
delete it;
}
Another reasonable approach would be to pass n to the Itch constructor and have it do the calculations there instead of in Scratch, perhaps even allowing Itch to determine N, e.g.:
class Itch {
private:
int N;
public:
Itch (int n);
int getN () const { return N; }
}
Itch::Itch (int n) {
// do some silly things
int temp = 5;
temp += n + 45;
N = temp - 1;
}
Scratch::Scratch (int n) : it(n) {
// you can either remove Scratch::N altogether, or I suppose do:
N = it.getN();
// ... do whatever makes sense, try not to have redundant data.
// (also ask yourself if Scratch even *needs* to know N, or at
// least if it can just use it.getN() everywhere instead of
// keeping its own copy.)
}
Another approach, which IMO is a bit odd but it's still possible in some situations, is to have e.g. a static function (member or not) that computes N from n, which you can use in the initializer list, e.g.:
static int doSillyThings (int n) {
int temp = 5;
temp += n + 45;
return temp - 1;
}
Scratch::Scratch(int n) : N(doSillyThings(n)), it(N)
{
}
Choose whichever leads to the cleanest, most maintainable and easy-to-read code. Personally I'd prefer the first, Itch * option, since it makes logical sense and is very clear: You do the calculations necessary to initialize the Itch, then you initialize it.
You should think about your code a bit. If the Scratch's N is always equal to it.N, then do you really need both Ns?
There are other options too (including restructuring your code completely so you don't have to have an Itch member of Scratch, or so that you don't have to have it depend on extra calculations done on the Scratchs constructor parameters but that really depends on the situation), but hopefully that inspires you a little.
The reason your code returns garbage, by the way, is because N is garbage at the point you pass it to the Itch constructor. It's uninitialized until you initialize it, and at the point where it(N) is you haven't initialized N yet.
I have some C code where I need to do some calculations with an array of data. The data can be either INT or DOUBLE. In order to deal with the different data types, I was thinking of using an if / else statement and define the pointer holding the data inside that statement:
/* put values into M, depending on data type*/
if (data_type == 2)
{
double *M;
M = somefunction(DOUBLE);
} else {
unsigned int *M;
M = somefunction(UINT16);
}
/* dummy code - usually I do some calculations on M which are data type independent */
for (i=0;i<(10);i++) {
M[i]=0;
}
This leads to scoping problems because M is not defined outside the if / else construct:
error: ‘M’ undeclared (first use in this function)
If I move the definition of M outside the if / else statement, the code will compile but M inside the if / else is a different M outside.
So I can circumvent the problem by defining two pointers, one double and one int and check everywhere in my code which type I'm dealing with:
double *Mdouble;
unsigned int *Mint;
/* put values into M, depending on data type*/
if (data_type == 2)
{
Mdouble = somefunction(DOUBLE);
} else {
Mint = somefunction(UINT16);
}
/* dummy code - usually I do some calculations on M which are data type independent */
for (i=0;i<(10);i++) {
if (data_type == 2) {
Mdouble[i]=0;
} else {
Mint[i]=0;
}
}
So here's my question:
How can I solve this problem where M is a double or int, depending on my incoming data? Could I solve this with some kind of pointer to a pointer work around? I don't want to write duplicate code for each case.
EDIT could template functions or overloading of functions solve my problem? I'm flexible regarding a C / C++ specific solution
You're going to have to write duplicate code.
At the base level, the required machine code for adding two numbers is different for integers vs floating-point numbers.
This difference is "hidden" since data is typed, so the compiler always knows the type of each operand and can generate the proper code.
If you want to move that information until run-time, the compiler can no longer do its thing, so you're going to have to do it instead and make sure your code takes the proper path.
You can try to use an C union:
#include <string.h>
#include <stdio.h>
int main(int argc, char** argv) {
union MyUnion {
int I;
double D;
};
union MyUnion M[10];
// Initializing the array to 0 (data type independent)
memset(M, 0, 10*sizeof(MyUnion));
M[0].I = 1;
M[1].D = 1.5;
if (argc==1) { // It should be "if (data_type==2) {"
// but I wanted an example that compiles easily
printf("%i\n", M[0].I); //somefunction(M[0].I);
} else {
printf("%lf\n", M[1].D); //somefunction(M[1].D);
}
}
In C you will have to use a macro
int8_t* ptr=...;
while(n)
{
switch(data_type)
{
case TYPE_DOUBLE:
A_MACRO_THAT_DEFINES_YOUR_OPERATION((double*)ptr);
ptr+=sizeof(double);
break;
case TYPE_INT:
A_MACRO_THAT_DEFINES_YOUR_OPERATION((int*)ptr);
ptr+=sizeof(int);
break;
}
--n;
}
This solution is slow since it needs to test the data type for each element. You can instead write the entire loop as a macro. This will be faster but harder to read.
If you can use C++, use a template instead. Here is a solution using templates:
template<class T>
void doStuff(T* ptr_begin,T* end)
{
while(ptr_begin!=ptr_end)
{
// Do stuff
++ptr_begin;
}
}
void doStuffWrapper(void* ptr_begin,void* ptr_end,uint32_t type)
{
switch(type)
{
case TYPE_DOUBLE:
doStuff((double*)ptr_begin,(double*)ptr_end);
break;
case TYPE_INT:
doStuff((int*)ptr_begin,(int*)ptr_end);
break;
}
}
As a side note: I prefer switch-case over if-else in this case since it is easier to maintain, and may produce faster code.
You can use a macro, e.g.:
#define CALCULATIONS(M) do { \
for (i=0;i<(10);i++) \
(M)[i]=0; \
} while (0)
and then in your other code:
if ( data_type == 2 )
{
double *M = whatever;
CALCULATIONS(M);
}
See here if you are unfamiliar with the do...while(0) technique
It sounds like you want a templatized function.
But I think the question comes down to, can you put all your work in the function?
template <typename T>
T* somefunction(T data){
//start old somefunction code
T* result = new T[10]{data, data, data, data, data, data, data, data, data, data};
//end old somefunction code
//begin "calculations on M which are data type independent"
for(int i = 0; i < 10; i++){
M[i] = 0;
}
return M;
}
So with the above code you could do either double* Mdouble = somefunction(13.13) or short* Mshort = somefunction(13);
The best case scenario is in which M was really a throw away array anyway, in which case you could even allocate the data in the template function's stack frame and avoid using new.
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
In C++ why can’t I write a for() loop like this: for( int i = 1, double i2 = 0; …
A C developer would write this:
int myIndex;
for (myIndex=0;myIndex<10;++myIndex) ...
A C++ developer would write this to prevent the loop variable from leaking outside the loop:
for (int myIndex=0;myIndex<10;++myIndex) ...
However, if you have 2 loop variables, you cannot do this anymore. The following doesn't compile:
for (int myIndex=0,MyElement *ptr=Pool->First;ptr;++myIndex,ptr=ptr->next) ...
The comma operator does not allow two variables to be defined this way, so we have to write it like this:
int myIndex;
MyElement *ptr;
for (myIndex=0,ptr=Pool->First;ptr;++myIndex,ptr=ptr->next) ...
Which defeats the advantage of having real loop-local variables.
A solution could be to put the whole construction between braces, like this:
{
int myIndex;
MyElement *ptr;
for (myIndex=0,ptr=Pool->First;ptr;++myIndex,ptr=ptr->next) ...
}
But this is hardly more elegant.
Isn't there a better way of doing this in C++ (or C++0x)?
You just have to understand the first statement is a declaration (and that comma is not the comma operator). It's not any harder to do:
for (int i, double d; ...)
Than it is:
int i, double d;
Because for (init cond; expr) statement gets expanded to:
{
init
while (cond)
{
statement
expr;
}
}
A trick is to make that init statement a struct definition and instance, like:
for (struct { int myIndex; MyElement* ptr;} data = {0, Pool->First};
data.ptr;
++data.myIndex, data.ptr = data.ptr->next)
{
// blah...
}
Which becomes the same as:
{
struct
{
int myIndex;
MyElement* ptr;
} data = {0, Pool->First};
while (data.ptr)
{
{
// blah...
}
++data.myIndex, data.ptr = data.ptr->next;
}
}
But I find that pretty ugly. In practice, I'd just split it up like you have. If scope is really a problem, which it probably isn't, throw the extra braces around there.
I don't think there's much to improve here without a bit of boilerplate code.
If I really wanted to confine the scope to the loop I would use:
#include <utility>
for (auto i = std::make_pair(0,Pool->First);
i.second;
++i.first, i.second=i.second->next)
At least C++ allows us to declare variables in the if clause, which which is sometimes used to declare a variable that only is only visible when some condition is true:
if (MyElement *ptr=Pool->First) // block is only entered when ptr!=0
{
for (int myIndex=0;ptr;++myIndex,ptr=ptr->next)
{
}
}
// ptr is out of scope now.
This could be a method to limit the scope of ptr and index, while maintaining readability.