Check whether structs members have changed from the default?

Hi

say i have a struct like this:
1
2
3
4
5
struct example
{
  int ex_value_1 = 435;
  int ex_value_2 = 325;
}


and i have an instance of that struct,
is there then a way to check whether / compare if the instanced struct's member variables are different from the default structs members?

So something like this (except this doesn't work)
1
2
if(my_struct_instance.ex_value_1 == example::ex_value_1)
  cout << "ex value 1 has not been changed\n";
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>

struct example {
  static const int VAL1_DEFAULT = 123;
  static const int VAL2_DEFAULT = 456;
  int val1 = VAL1_DEFAULT;
  int val2 = VAL2_DEFAULT;
  bool isDefault() {return val1==VAL1_DEFAULT&&val2==VAL2_DEFAULT;}
};

int main() {
    example e1, e2;
    e1.val1 = 789;
    if (e1.isDefault()) std::cout << "e1 is unchanged\n";
    if (e2.isDefault()) std::cout << "e2 is unchanged\n";
}

Thanks.
But unfortunatly my struct has quite alot of members variables
and i actually have multiple of these big structs that i need to check.

I also need to check just a single member at a time not every member, so i would have to make a isDefault function for every single member variable.
So im not so sure this solution will work for me :\

is there a "lighter" way to achieve it?

like the example?
Last edited on
You can't have "ex_value_1" refer to two different things within the same class.
The following is similar to tpb's but closer to your first example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Example program
#include <iostream>
#include <string>

struct example
{
    int ex_value_1 = ex_value_1_default;
    int ex_value_2 = ex_value_2_default;
    
    static const int ex_value_1_default = 435;
    static const int ex_value_2_default = 325;
};

int main()
{
    example my_struct_instance;
    
    my_struct_instance.ex_value_2 = 42;
    
    if (my_struct_instance.ex_value_1 == example::ex_value_1_default)
        std::cout << "ex value 1 has not been changed\n";
        
    if (my_struct_instance.ex_value_2 == example::ex_value_2_default)
        std::cout << "ex value 2 has not been changed\n";

}


_____________________________

Logically, if you want to compare to default values, you're going to have to store them somewhere. You can't avoid this.
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
using namespace std;

struct example
{
  int a = 435;
  int b = 325;
};

const example EXAMPLE;                       // One, constant, default structure

bool isChanged( example e, int example::*ptr ) { return e.*ptr != EXAMPLE.*ptr; }


int main()
{
    example e1, e2;
    int example::*ptr;
    
    ptr = &example::a;         // Choose which member to point to
    
    for ( auto e : { e1, e2 } ) cout << boolalpha << isChanged( e, ptr ) << '\n';
    
    cout << "----\n";
    
    e1.a = 440;
    for ( auto e : { e1, e2 } ) cout << boolalpha << isChanged( e, ptr ) << '\n';
}
Well that's new syntax to me.

Can you explain what int example::*ptr; means?
pointer to int... but restricted to only being able to point to an int member of example? Didn't know such a restriction was possible in C++.
Last edited on
Can you explain what int example::*ptr; means?

Look up "pointer to member function". It's a kind of "offset" pointer that can only be called off of an object of the correct type. In lastchance's case, it's a pointer to a member variable, but it's the same idea. He accesses the member variables through the global EXAMPLE object.
Last edited on
Hi Ganado - it's a pointer to data member
http://en.cppreference.com/w/cpp/language/pointer (about half way down).

I can safely say it's the first time I've ever used one!
Ganado> your way of doing is better since it's shorter and clearer.

The int blabla::*p only means a pointer to a member variable that is an int. So if you have a lot more type in your class, that'll be a hell to implement. But, macros existed for sure :oD.

The use of a defauft constant object though is very interesting in lastchance's solution.

Combining both yours (Ganado) and lastchance, the solution is really good.

1
2
3
4
5
6
7
8
9
10
11
12
struct example
{
    int ex_value_1 = 45;
    int ex_value_2 = 111;
};

const example EXAMPLE;

...

    if(my_struct_instance.ex_value_1 == EXAMPLE::ex_value_1)
        std::cout << "ex value 1 has not been changed\n";


stav> I really don't like struct... to me it's the kind of "class" for lazy people. And here is an example of that "laziness".
If you use a non-defaut constructor to define your object, then you can explicitely mark a change in default value... if this was what you want ?
Or do you just want to check that the current value is not the default one ?
Last edited on
Obviously derived from lastchance's idea.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
using std::cout;

struct example {
  int val1 = 123;
  int val2 = 345;
  long val3 = 123123123123;
  double val4 = 1.23;
};

const example EXAMPLE_DEFAULT; // holds original defaults

template <typename T>
bool isDefault(example& ex, T example::*p) {
    return ex.*p == EXAMPLE_DEFAULT.*p;
}

#define ISDEFAULT(e,v) isDefault((e), &example::v)

int main() {
    example e1, e2;
    e1.val1 = 789;
    e2.val4++;

    cout << "e1.val1 ";
    if (ISDEFAULT(e1, val1)) cout << "un"; cout << "changed\n";

    cout << "e2.val1 ";
    if (ISDEFAULT(e2, val1)) cout << "un"; cout << "changed\n";

    cout << "e1.val3 ";
    if (ISDEFAULT(e1, val3)) cout << "un"; cout << "changed\n";

    cout << "e2.val4 ";
    if (ISDEFAULT(e2, val4)) cout << "un"; cout << "changed\n";
}

Last edited on
That's very nice @tpb!

I was trying to template it too, but kept muffing it. Hard day at work has befuddled my brain.
I had to resort to a macro to get rid of the ugly &example::, though. ;-(
Last edited on
Topic archived. No new replies allowed.