Compile time hints/warnings on struct changes - c++

I have a basic POD struct with some fields
struct A{
int a,
int b,
};
The nature of my use case requires that these fields change every so often (like 1-2 months, regular but not often). This means that I want to check the field usages of the struct after the changes to make sure everything is still fine.
The compiler checks that all field usages are valid, something like a.c will fail at compile time.
However, some of my functions should access and handle ALL of the fields of A. So while the compiler verifies that all usages are valid, it doesn't validate that all the fields are used.
This work/checking must be done manually (if there is a way to do this at compile time, please enlighten me). So our current design tries to make this as easy as possible. We grouped most of the relevant functions into one folder/library so we could check over them in one place. However, some usages are embedded in private class functions that would honestly be more of a pain to refactor out into the common lib than the benefits it brings.
It's reasonable to just rely on documentation saying "Hey, after changing struct A, check the function foo in class FooThing". But I'm looking to see if we can get some type of compile time warnings.
My idea was to basically drop a static_assert next each relevant function that would check the size of A. Most changes should change the size, so an unchanged static_assert would fail at compile time, pointing me to the general area of the function. Then I could just change the function and the assert.
So besides the function foo for example, I would have something like static_assert(sizeof(A) == 16) or whatever size. This isn't foolproof, as it's possible that changes to struct might not change the total size, but I'm not looking for something really rigorous here, just something that could be helpful 90% of the time.
The main reason why this doesn't work for me is that int and other data types don't have a specified size from the standard. This is a problem for me since my project is cross platform.
In short, I am looking for a way to signal at compile time to check certain functions after a struct's definition has been changed.

One possibility is to put a version number into the struct itself, like so:
struct A{
int a;
int b;
static constexpr int major_version = 1;
};
Then, in calling code, you place assertions that check the value of the major version:
void doSomething(A a)
{
static_assert(A::major_version == 1, "Unexpected A major version");
// Do something with a
}
Then, any time you make an update to A that you think merits re-inspection of all calling code, you increment A::major_version, and then the static_assert will fire anywhere you haven't changed it.

Related

How do i pass initial setup values to a templated class in a succinct way?

this is a VERY simplified version of the question to make it obvious what i am asking. I cannot seem to find it on Stack Overflow but i am probably searching using the wrong words!
Here is a Template Class with the obvious parts removed.
template <class T, bool clip = true>
class BOUNDED_VAL {
public:
BOUNDED_VAL(T initialMin, T intialMax) :locked(false) {
assert_or_throw(intialMax >= initialMin, HD_ERR_MINMAX_REVERSED);
min = initialMin;
max = intialMax;
value = initialMin;
};etc.
// assert_or_throw is a typedef which asserts during debug builds to prevent programmer mistakes (especially my own) or throws a rich catachable runtime error for user input just in case something gets around user input limit checking during release builds (A hard wall). Belt and braces approach...
Now i know i can set this up as an initialised private class member variable like so:
private:
BOUNDED_VAL<int> testBoundInt = BOUNDED_VAL<int>(0, 10);
BUT
Does this create a new BOUNDED_VAL and then copy it over the member variable (or compiler smooshes this away during optimisation)?
Is there a more succinct way of doing it which i am just not finding? I know the following do not work but for example:
private:
BOUNDED_VAL<int> testBoundInt(0,10);
or
private:
BOUNDED_VAL<int>(0,10) testBoundInt;
I am self taught in C++ so it might be an obvious question...but you never know...
Many Thanks
I know the following do not work but for example:
private:
BOUNDED_VAL<int> testBoundInt(0,10);
But this will work, provided your compiler was written in the last decade:
BOUNDED_VAL<int> testBoundInt{0,10};
It looks like you might be using an outdated textbook to learn C++ that does not cover uniform initialization syntax from the current version of C++. You are strongly encouraged to get updated learning material.
Does this [copy initialization] create a new BOUNDED_VAL and then copy it over the member variable (or compiler smooshes this away during optimisation)?
This actually depends on the C++ version your compiler supports, and is configured to use. Depending on several factors it gets "smooshed" away, or we take a scenic trip to the countryside, where an object gets constructed, then a second object gets copy-constructed, and the first object deleted.
But this is now a secondary topic, since uniform initialization syntax solves the original problem.

Detecting duplicate work at compile time within C++ code

lets consider the following code:
struct Foo {
Foo(Bar b1, Bar b2) : b1(b1), b2(b2) {}
void work() {
b1.work();
b2.work();
//something
}
Bar& b1;
Bar& b2;
};
struct Bar {
void work() { /* something */ }
};
int main() {
Bar a, b;
a.work();
//something...
Foo c(a,b);
c.work();
//something...
}
The way I wrote that (or intended to write it), a.work() will get executed twice. But let's say, I, as the programmer know, that executing it twice is a waste of execution time and let's say this was part of a far more complex piece of software where it would be far too troublesome to keep track manually what work is and isn't done.
Obviously I could store some boolean flag in Bar and check every single time whether the work has been done already, but I want to know, if there is some way where I can already catch that at compile time. Because at compile time it is already clear that the work had been done.
Another approach. Have a function pointer within the Bar object and in work() function call the pointer. In the constructor, define the pointer to be the actual work function. At the end of the function, reassign the pointer to be an empty function.
In this case, the first execution will do the job. But later executions will do nothing (also not checking the boolean flag)
struct Bar {
typedef void (*Bar::fptr_t)();
Bar() : fptr(actual_work) {}
void actual_work() {
/*something*/;
fptr = &Bar::empty_work;
}
void empty_work() {}
void work() {fptr();}
fptr_t fptr;
};
Something like above.
No, not really.
The compiler is capable of some static analysis, and if you could ask it to diagnose this condition, it may be able to do so in some simple cases. But as soon as you have a non-trivial flow (runtime if conditions, for example), that goes out of the window very quickly. That's probably part of the reason that nobody has created such a programmable feature for compilers: high complexity, with negligible utility.
It may be possible to program some third-party static analysers (or create one!) to diagnose your simple case, but again that's a lot of work for handling only the most trivial cases that you can already spot with your eyes.
Instead, you could make work() happen in the Bar constructor. Then it's impossible to do the work twice on the same object. However, performing large quantities of work in a constructor is often frowned upon.
I would indeed keep a state flag within Bar, and return false from a subsequent work(), by maintaining the value of that flag accordingly. As a bonus, stick an assertion in the function before returning false so that you catch violations during your testing.
The state flag doesn't have to be a boolean; it can be an enum. Robust state machines inside your objects can be very helpful.
That being said, I'd advise revisiting your current approach where you pass references to things into other things that do work on them; it's not an easy-to-follow design, and this is only a simple example of your design! You may wish to consider passing some single-use proxy type instead.
Actually, at compile time it isn't obvious, whether the code was executed or not. Suppose you have an if statement and within it, you call a.work(). How does the compiler know, whether at that time the a.work() was executed? As you say, don't think, that the if statement is very simple (suppose, it is looking for some external signal and executes the code depending on that signal). The best way to avoid the behavior is to keep a boolean.

How to imply array-length (const int) at compile time from complex code

How to determine array-length (#) at compile time from a complex code?
In my code, if I skimmed it, I can know how much array-size it is needed, but the related algorithm is scattering around many .h/.cpp.
(Sorry for an obscure title and introduction, I don't really know what the problem is called.)
A solid example (demo)
I want to create many type of relation 1:1 between many game objects.
Library code (static library)
GO.h (game-object): store pointer to another-one.
class GO{//game object
public:
static const int numRelation=10; //#
GO* left[numRelation];
GO* right[numRelation];
public: GO(){
for(int n=0;n<numRelation;n++){
left[n]=nullptr;
right[n]=nullptr;
}
}
};
DB.h (Database): It is a utility. It stores index of relation in userIndex.
class DB{//database
int userIndex=-42;
public: DB(){};
public: DB(int us){userIndex=us;}
public: GO* getLeft(GO* g){return g->left[userIndex];}
public: void createRelation(GO* g1,GO* g2){
g2->left[userIndex]=g1;
g1->right[userIndex]=g2;
}
};
DBGenerator.h (Database-Generator) :
It is a central system to help cooperation of many other sub-system.
It generates userIndex for DB.
class DBGenerator{//quite singleton
int indexCounter=0;
public: DB generate(){return DB(indexCounter++);}
};
User code (game-specific)
CageManager.h has two 1:1 relation : hen-food and hen-cage.
FamilyManager.h has one 1:1 relation hen-egg.
class CageManager{
DB dbHenFood;
DB dbHenCage;
public: CageManager(DBGenerator* gen){
dbHenFood=gen->generate();
dbHenCage=gen->generate();
}
};
class FamilyManager{
DB dbHenEgg;
public: FamilyManager(DBGenerator* gen){
dbHenEgg=gen->generate();
}
};
The userIndex will be reserved like this :-
I can add relation and query e.g. :-
int main() {
DBGenerator commander;
CageManager m1{&commander};
FamilyManager m2{&commander};
GO* hen=new GO();
GO* egg=new GO();
m2.dbHenEgg.createRelation(hen,egg);
GO* henGet=m2.dbHenEgg.getLeft(egg);
if(henGet==hen)std::cout<<"correct";
if(henGet!=hen)std::cout<<"wrong";
return 0;
}
Question
The above code works OK. (coliru demo, ideone backup)
However, as my game grows, I need more slot.
If the amount of slots exceeds 10, I have to edit the figure (const int numRelation=10) in GO.h manually.
Another trouble is that : if I want to create a new game,
I need to modify GO.h to ensure that it will be enough (but not too much - waste memory) for the new game-logic.
How to make such variable (const int numRelation) to always has a correct figure (3 in this test)?
Other note:-
I want to avoid heap allocation, so the size of array have to be fixed.
It is performance-critical, because the database is called excessively.
I don't know if there is an elegant way.
From what I want, GO.h will probably have to include those two manager.h.
It may break the whole architecture. (???)
As a general rule, constexpr finishes execution before link time. So you cannot have a constexpr term whose value depends on things in different compilation units.
Your singleton value of "number of relations" thus cannot be calculated at compile time, nor can the index of each relation be calculated at compile time.
As a first attempt, we can get around this by asking each relation to pick a number, then verify there is no conflict. If checked at compile time, this would generate a constexpr value that depends on different compilation units; thus impossible.
We can check for "is the index we picked in bounds" at compile time. We can check "is there a collision" at runtime.
If we do this at static initialization time, and we require that a single line be inserted at main, we can detect if there is wasted space as well.
Replace the generation of DBs with a requirement that each relation claim an index. Have the indexes be checked to be in bound. At runtime, at the start of main, validate that there are no holes in your index table. This keeps relations decoupled from each other (they don't have to know about each other).
Now, this won't work if you expect to have an engine reused in multiple different projects with a different number of relations, because one will develop holes that the other doesn't want.
We could back up our requirement; remove the need to manually write constexpr indexes, and have those also generated at startup (like your code does). We simply add in runtime checks for "am I beyond bounds" and another check for "did we waste space" injected in helper at the start of main.
Now we get decoupling, no wasted indexes, and no manual index management. There is a trivial startup cost (which basically matches what you pay with the above code).

How to use the C++ compiler/linker/trick to detect a value that is assigned but never subsequently referred to?

I want to make a singleton class, call it global_references containing a bunch of cached global values. The singleton class code will be automatically generated from a set of tables. The general scheme is something like this:
global_references.h
struct global_references
{
some_type value1;
some_type value2;
some_type value3;
...
static const global_references& instance();
};
Assume that global_references::instance() initializes the various valueN variables and returns the singleton instance. Then various clients will used the cached values in their own code:
some_translation_unit.cpp
...
x = global_references::instance().value1;
My concern is that I will add items to the table that is used to produce the auto-generated global_references class but over time, some of the symbols they generate will become obsolete and stop being used in the program. I would like to know when this happens, preferably by having the compiler or linker complain about an unused symbol, or a value that is assigned but never used. This will remind me to go delete the corresponding item from the table. I am also open to any other reasonably simple solution.
I am using MinGW [g++ 4.6.2] on Windows.
Options Already Considered
I thought about making member functions to return the values, but the The -Wunused-function compiler option only works on static functions whereas I need global_references to be a modular component which I can include in any translation unit.
Use -Wunused-but-set-variable, or for broader effect, -Wunused, or -Wall.
I am not sure that I have understood your purpose. So, after you add items to the table each time, you will recompile the project code to find what is not used by compile-warning. It Sounds like an inefficient way.

What is easiest way to force compiler to throw error?

To the folks marking this as duplicate: it is not; the other question addresses enums which are compile-time constants. This is not a constant integral expression thus the solution would be very different. Please see my code below more carefully before suggesting this has already been answered in another question, as it has not in any way. I am checking the value of a member variable on an object, information created at runtime, and I'm curious what I can do with that in this context.
I'm at a point where I need to use something to make the compiler fail if the user of my API does something she should not.
I don't know if that's possible, it is? The options I mention above are primarily run-time, right?
For example, suppose you have a function:
void doSomethingIncredible(AwesomeClass amazingObject)
{
//perform life-changing work here except:
if (amazingObject.isntAmazing) //a bool property of object
//uh oh, life sucks, I refuse to compile this
Now calling this function will change how you live your life in all respects, except for occasions in which amazingObject has a particular property switched on, for example, in which case, I want the compiler to not even allow this to pass, i.e. cannot run the program.
Somewhere in the body of the function is a c++ mechanism that forces compiling to fail, which alerts the user that you cannot use this function for such an inferior un-amazing object.
Is this possible?
To clarify, this is something I want to do a compile time based the contents of a variable, as shown in my example above. The suggestion to use static_assert does not apply here.
You can either static_assert() a condition at compile time (C++11)
static_assert(false, "Hey user! You suck!");
or use
#if (some_erroneous_condition_to_be_avoided)
#error "Hey user! You suck!"
#endif
if you have a GNU-compatible compiler (g++, clang++, etc.)
The only way I can see to get it compile time checked is to subclass AwesomeClass and restrict the new class' creation to only be able to create objects where amazingObject.isntAmazing is never true. Then change the signature to;
void doSomethingIncredible(AwesomeAndAmazingClass amazingObject)
That will prevent the call to the method for objects that are simply awesome but not amazing.
As a maybe more illustrative example (not compiled, so consider pseudo code);
class Thing {
protected:
Color _color;
Shape _shape;
public:
Thing(Color color, Shape shape) {
_color=color; _shape=shape;
}
}
class GreenThing : Thing {
public:
GreenThing(Shape shape) : Thing(Color.Green, shape) {}
}
void doSomethingIncredible(GreenThing specialThing)
{
// specialThing here is still a Thing, but also compile time
// checked to also always be a GreenThing
}
It is impossible. The value of the variable is decided at runtime, but you want to throw a compile-time error depending on the runtime value.