C++: Global variable vs local variables. What to use? - c++

Sometimes I wanna use globals but instead of it I use local variables. Let we have some Font class:
class Font {
public:
class Alignment {
public:
unsigned short currentAlignment;
unsigned short FONT_ALIGN_LEFT = 0;
unsigned short FONT_ALIGN_CENTER = 1;
unsigned short FONT_ALIGN_RIGHT = 2;
// etc....
};
Alignment alignment;
void setFontAlignment( unsigned short fontAlignment ) {
this->alignment.currentAlignment = fontAlignment;
}
};
To use this class we need to do something like that:
Font font;
font.setFontAlignment( font.alignment.FONT_ALIGN_CENTER );
// if we need to check currentAlignment we need to do:
if ( font.alignment.currentAlignment == font.alignment.FONT_ALIGN_CENTER ) {...} // looks a little bit awful :)
Or we have another approach to do this:
= Font.h =
#define FONT_ALIGN_LEFT 0
#define FONT_ALIGN_CENTER 1
#define FONT_ALIGN_RIGHT 2
// etc....
class Font {
public:
unsigned short currentAlignment;
void setFontAlignment( unsigned short fontAlignment ) {
this->currentAlignment = fontAlignment;
}
}
To use this:
#include "Font.h"
...
Font font;
font.setFontAlignment( FONT_ALIGN_CENTER );
if ( font.currentAlignment == FONT_ALIGN_CENTER ) {...} // looks a little bit better :)
Which one is better for memory optimizing and why? Which one do you prefer to use? Or maybe you know some better solutions?

Although there are always exceptions, I usually go by (among others :-) the following guidelines:
Avoid globals as much as possible. Confine to smallest applicable
scope (within reason).
Avoid second guessing the compiler, except for grossly obvious
situations.

Actually, a combination of them. But let's clarify something. You don't speak about any global variable in your question. A global variable is a variable defined in the global scope.
The primary reason of using object oriented programming is not its efficiency (as it is slower than purely procedural code), but its ability to model the world. So, when creating an oop design, you shouldn't care too much about the resourced (time, memory), but how good it models the world.
The second version is bad, because it introduces a lot of constants in the global scope, and you want to avoid that. Also, it does a very bad job at encapsulating the data (the user of your Font class shouldn't care about the values of the alignment).
The first version is better, but there are some problems. First, you need to think about the objects you should have? Do you actually need an Alignment object? You may need it, but in this particular example, I don't see why. So, you could make it model the world as it is, without introducing some artificial elements:
class Font {
public:
unsigned short currentAlignment;
void alignLeft() {
this->currentAlignment = 0;
}
void alignCenter() {
this->currentAlignment = 1;
}
void alignRight() {
this->currentAlignment = 2;
}
};
Now it is very easy to use. I don't have to keep in my global scope unnecessary constants. Now, the problem is what happens when the user reads the value of the currentAlignment? Of course, you don't want to use the constants, but you don't need to. It really depends on the world you're modelling. As this is a Font class, it should be the only one who really cares about the value of the alignment. If somebody else needs the value, you could have some methods like isCenter() that return true when the font is center-aligned. But also, I would consider making the currentAlignment private.

Related

Declaring enum as loop boundary [duplicate]

What is the purpose of anonymous enum declarations such as:
enum { color = 1 };
Why not just declare int color = 1?
That's a so-called enum trick for declaring a compile-time integer constant. It's advantage is it guarantees that no variable is instantiated and therefore there's no runtime overhead. Most compilers introduce no overhead with integer constants anyway.
Enums don't take up any space and are immutable.
If you used const int color = 1; then you would solve the mutability issue but if someone took the address of color (const int* p = &color;) then space for it would have to be allocated. This may not be a big deal but unless you explicitly want people to be able to take the address of color you might as well prevent it.
Also when declaring a constant field in a class then it will have to be static const (not true for modern C++) and not all compilers support inline initialization of static const members.
Disclaimer: This answer should not be taken as advice to use enum for all numeric constants. You should do what you (or your co-workers) think is more readable. The answer just lists some reasons one might prefer to use an enum.
If this is old code, then enum might have been used for the "enum hack".
You can learn more about the "enum hack", for example, in this link: enum hack
In short: this allows defining the value once, just like #define or defining a variable, but unlike #define - here the compiler makes sure that the value is a number (int, r-value) and prevents you from doing all kinds of mischief that you can do with the precompiler's simple "search and replace", and unlike defining a variable - never takes up space under any compiler or configuration, and prevents changes to it (even const variables can sometimes be changed if you try hard enough).
(1) int color = 1;
color is changeable (accidently).
(2) enum { color = 1 };
color cannot be changed.
The other option for enum is,
const int color = 1; // 'color' is unmutable
Both enum and const int offer exactly same concept; it's a matter of choice. With regards to popular belief that enums save space, IMO there is no memory constraint related to that, compiler are smart enough to optimize const int when needed.
[Note: If someone tries to use const_cast<> on a const int; it will result in undefined behavior (which is bad). However, the same is not possible for enum. So my personal favorite is enum]
One use of this is when you're doing template metaprogramming, because enum objects are not lvalues, while static const members are. It also used to be a common workaround for compilers that didn't let you initialize static integral constants in the class definition. This is explained in another question.
When you use
enum {color = 1}
you're not using any memory it's like
#define color 1
If you declare a variable
int color=1
Then you're taking up memory for a value that's not to be changed.
Answer
Readability and performance.
Details are describbed as notes to examples below.
Use cases
Personal example
In Unreal Engine 4 (C++ game engine), I have following property (engine exposed member variable):
/// Floor Slope.
UPROPERTY
(
Category = "Movement",
VisibleInstanceOnly,
BlueprintGetter = "BP_GetFloorSlope",
BlueprintReadOnly,
meta =
(
ConsoleVariable = "Movement.FloorSlope",
DisplayName = "Floor Slope",
ExposeOnSpawn = true,
NoAutoLoad
)
)
float FloorSlope = -1.f;
This is a value of floor slope player is standing on (value ∈ [0; 90)°), if any.
Because of engine limitations, it cannot be neither std::optional nor TOptional.
I've came up with a solution to add another self explainable variable bIsOnFloor.
bool bIsOnFloor = false;
My C++ only internal setter for FloorSlope takes the following form:
void UMovement::SetFloorSlope(const float& FloorSlope) noexcept
contract [[expects audit: FloorSlope >= 0._deg && FloorSlope < 90._deg]]
{
this->bIsOnFloor = true;
this->FloorSlope = FloorSlope;
AUI::UI->Debug->FloorSlope = FString::Printf(L"Floor Slope: %2.0f", FloorSlope);
};
Adding special case where FloorSlope parameter would take argument of -1.f would be hard to guess and not user friendly.
Instead, I'd rather create False enum field:
enum { False };
This way, I can simply overload SetFloorSlope function that takes intuitive False instead of -1.f.
void UMovement::SetFloorSlope([[maybe_unused]] const decltype(False)&) noexcept
{
this->bIsOnFloor = false;
this->FloorSlope = -1.f;
AUI::UI->Debug->FloorSlope = L"Floor Slope: —";
};
When a player character hits a floor upon applying gravity to it on tick, I simply call:
SetFloorSlope(FloorSlope);
… where FloorSlope is a float value ∈ [0; 90)°.
Otherwise (if it does not hits a floor), I call:
SetFloorSlope(False);
This form (as opposed to passing -1.f) is much more readable, and self explanatory.
Engine example
Another example may be to prevent or force initialization.
Mentioned above Unreal Engine 4 commonly uses FHitResult struct containing information about one hit of a trace, such as point of impact and surface normal at that point.
This complex struct calls Init method by default, setting some values to certain member variables. This can be forced or prevented (public docs: FHitResult #constructor):
FHitResult()
{
Init();
}
explicit FHitResult(float InTime)
{
Init();
Time = InTime;
}
explicit FHitResult(EForceInit InInit)
{
Init();
}
explicit FHitResult(ENoInit NoInit)
{
}
Epic Games defines such enums similiar, but adds redundant enum names:
enum EForceInit
{
ForceInit,
ForceInitToZero
};
enum ENoInit {NoInit};
Passing NoInit to the constructor of FHitResult prevents initialization, what can lead to performance gain by not initializing values that will be initialized elsewhere.
Community example
FHitResult(NoInit) usage in DamirH's post on Comprehensive GameplayAbilities Analysis Series:
//A struct for temporary holding of actors (and transforms) of actors that we hit
//that don't have an ASC. Used for environment impact GameplayCues.
struct FNonAbilityTarget
{
FGameplayTagContainer CueContainer;
TWeakObjectPtr<AActor> TargetActor;
FHitResult TargetHitResult;
bool bHasHitResult;
public:
FNonAbilityTarget()
: CueContainer(FGameplayTagContainer())
, TargetActor(nullptr)
, TargetHitResult(FHitResult(ENoInit::NoInit))
, bHasHitResult(false)
{
}
// (…)
I dont see it mentioned, another use is to scope your constants. I currently work on code that was written using Visual Studio 2005, and it is now ported to android - g++. In VS2005 you could have code like this enum MyOpts { OPT1 = 1 }; and use it as MyOpts::OPT1 - and compiler did not complain about it, even though it is not valid. g++ reports such code as error, so one solution is to use anonymous enum as follows: struct MyOpts { enum {OPT1 =1}; };, and now both compilers are happy.

How to make data available to all objects of a class?

This is probably very basic but somehow I cannot figure it out.
Say I have a class A which embeds 42 Things, plus some common data:
class A {
Thing things[42];
int common_data[1024];
}
I would like each thing to have access to the common data, but I don't want to copy the data in each Thing object, nor pay the price of a pointer to it in each thing. In other word, I would like Thing to look like this:
class Thing {
int ident;
int f() {
return common_data[ident];
}
}
Of course here common_data is unbound. What is the canonical way to make this work?
FWIW I am working with a subset of C++ with no dynamic allocation (no "new", no inheritance, basically it's C with the nice syntax to call methods and declare objects); I am ideally looking for a solution that fits in this subset.
You can solve your issue by making the common_data attribute of Class A static. Static variables are shared by all members of class A, and will be accessible if you make it public.
class A
{
private:
Thing things[42];
public:
static int common_data[1024];
}
It can be accessed by doing...
A::common_data[index];
I am not sure if I understand the question correctly, but maybe this helps:
struct A {
Thing things[42];
int common_data[1024];
void foo(int index) {
things[index].doSomeThingWithCommonData(int* common_data);
}
};
struct Thing {
void doSomeThinWithCommonData(int* common_data) {
/* now you have access to common_data */
}
};
Your reasons for avoiding pointers/reference is based on irrational fears. "Copying" a pointer 42 times is nothing (read this word carefully) for the machine. Moreover this is definitely not the bottleneck of the application.
So the idiomatic way is to simply use dependency injection, which is indeed a slightly more costly action for you (if passing an array can be considered costly), but allows for a much more decoupled design.
This is therefore the solution I recommend:
struct Thing {
using data = std::shared_ptr<std::array<int, 1024>>;
data common_data;
Thing(data arg)
: common_data(arg)
{}
// ...
};
If the system is costrained, then you should benchmark your program. I can tell you already with almost absolutely certainty that the bottleneck won't be the copying of those 42 pointers.

Why does this C++ code use an anonymous enum rather than a const variable? [duplicate]

What is the purpose of anonymous enum declarations such as:
enum { color = 1 };
Why not just declare int color = 1?
That's a so-called enum trick for declaring a compile-time integer constant. It's advantage is it guarantees that no variable is instantiated and therefore there's no runtime overhead. Most compilers introduce no overhead with integer constants anyway.
Enums don't take up any space and are immutable.
If you used const int color = 1; then you would solve the mutability issue but if someone took the address of color (const int* p = &color;) then space for it would have to be allocated. This may not be a big deal but unless you explicitly want people to be able to take the address of color you might as well prevent it.
Also when declaring a constant field in a class then it will have to be static const (not true for modern C++) and not all compilers support inline initialization of static const members.
Disclaimer: This answer should not be taken as advice to use enum for all numeric constants. You should do what you (or your co-workers) think is more readable. The answer just lists some reasons one might prefer to use an enum.
If this is old code, then enum might have been used for the "enum hack".
You can learn more about the "enum hack", for example, in this link: enum hack
In short: this allows defining the value once, just like #define or defining a variable, but unlike #define - here the compiler makes sure that the value is a number (int, r-value) and prevents you from doing all kinds of mischief that you can do with the precompiler's simple "search and replace", and unlike defining a variable - never takes up space under any compiler or configuration, and prevents changes to it (even const variables can sometimes be changed if you try hard enough).
(1) int color = 1;
color is changeable (accidently).
(2) enum { color = 1 };
color cannot be changed.
The other option for enum is,
const int color = 1; // 'color' is unmutable
Both enum and const int offer exactly same concept; it's a matter of choice. With regards to popular belief that enums save space, IMO there is no memory constraint related to that, compiler are smart enough to optimize const int when needed.
[Note: If someone tries to use const_cast<> on a const int; it will result in undefined behavior (which is bad). However, the same is not possible for enum. So my personal favorite is enum]
One use of this is when you're doing template metaprogramming, because enum objects are not lvalues, while static const members are. It also used to be a common workaround for compilers that didn't let you initialize static integral constants in the class definition. This is explained in another question.
When you use
enum {color = 1}
you're not using any memory it's like
#define color 1
If you declare a variable
int color=1
Then you're taking up memory for a value that's not to be changed.
Answer
Readability and performance.
Details are describbed as notes to examples below.
Use cases
Personal example
In Unreal Engine 4 (C++ game engine), I have following property (engine exposed member variable):
/// Floor Slope.
UPROPERTY
(
Category = "Movement",
VisibleInstanceOnly,
BlueprintGetter = "BP_GetFloorSlope",
BlueprintReadOnly,
meta =
(
ConsoleVariable = "Movement.FloorSlope",
DisplayName = "Floor Slope",
ExposeOnSpawn = true,
NoAutoLoad
)
)
float FloorSlope = -1.f;
This is a value of floor slope player is standing on (value ∈ [0; 90)°), if any.
Because of engine limitations, it cannot be neither std::optional nor TOptional.
I've came up with a solution to add another self explainable variable bIsOnFloor.
bool bIsOnFloor = false;
My C++ only internal setter for FloorSlope takes the following form:
void UMovement::SetFloorSlope(const float& FloorSlope) noexcept
contract [[expects audit: FloorSlope >= 0._deg && FloorSlope < 90._deg]]
{
this->bIsOnFloor = true;
this->FloorSlope = FloorSlope;
AUI::UI->Debug->FloorSlope = FString::Printf(L"Floor Slope: %2.0f", FloorSlope);
};
Adding special case where FloorSlope parameter would take argument of -1.f would be hard to guess and not user friendly.
Instead, I'd rather create False enum field:
enum { False };
This way, I can simply overload SetFloorSlope function that takes intuitive False instead of -1.f.
void UMovement::SetFloorSlope([[maybe_unused]] const decltype(False)&) noexcept
{
this->bIsOnFloor = false;
this->FloorSlope = -1.f;
AUI::UI->Debug->FloorSlope = L"Floor Slope: —";
};
When a player character hits a floor upon applying gravity to it on tick, I simply call:
SetFloorSlope(FloorSlope);
… where FloorSlope is a float value ∈ [0; 90)°.
Otherwise (if it does not hits a floor), I call:
SetFloorSlope(False);
This form (as opposed to passing -1.f) is much more readable, and self explanatory.
Engine example
Another example may be to prevent or force initialization.
Mentioned above Unreal Engine 4 commonly uses FHitResult struct containing information about one hit of a trace, such as point of impact and surface normal at that point.
This complex struct calls Init method by default, setting some values to certain member variables. This can be forced or prevented (public docs: FHitResult #constructor):
FHitResult()
{
Init();
}
explicit FHitResult(float InTime)
{
Init();
Time = InTime;
}
explicit FHitResult(EForceInit InInit)
{
Init();
}
explicit FHitResult(ENoInit NoInit)
{
}
Epic Games defines such enums similiar, but adds redundant enum names:
enum EForceInit
{
ForceInit,
ForceInitToZero
};
enum ENoInit {NoInit};
Passing NoInit to the constructor of FHitResult prevents initialization, what can lead to performance gain by not initializing values that will be initialized elsewhere.
Community example
FHitResult(NoInit) usage in DamirH's post on Comprehensive GameplayAbilities Analysis Series:
//A struct for temporary holding of actors (and transforms) of actors that we hit
//that don't have an ASC. Used for environment impact GameplayCues.
struct FNonAbilityTarget
{
FGameplayTagContainer CueContainer;
TWeakObjectPtr<AActor> TargetActor;
FHitResult TargetHitResult;
bool bHasHitResult;
public:
FNonAbilityTarget()
: CueContainer(FGameplayTagContainer())
, TargetActor(nullptr)
, TargetHitResult(FHitResult(ENoInit::NoInit))
, bHasHitResult(false)
{
}
// (…)
I dont see it mentioned, another use is to scope your constants. I currently work on code that was written using Visual Studio 2005, and it is now ported to android - g++. In VS2005 you could have code like this enum MyOpts { OPT1 = 1 }; and use it as MyOpts::OPT1 - and compiler did not complain about it, even though it is not valid. g++ reports such code as error, so one solution is to use anonymous enum as follows: struct MyOpts { enum {OPT1 =1}; };, and now both compilers are happy.

dumb data object holds all common values c++, is this correct

So I am new to c++ and I'm writing for a scientific application.
Data needs to be read in from a few input text files.
At the moment I am storing these input variables in an object. (lets call it inputObj).
Is it right that I have to pass this "inputObj" around all my objects now. It seems like it has just become a complicated version of global variables. So I think I may be missing the point of OOP.
I have created a g++ compilable small example of my program:
#include<iostream>
class InputObj{
// this is the class that gets all the data
public:
void getInputs() {
a = 1;
b = 2;
};
int a;
int b;
};
class ExtraSolver{
//some of the work may be done in here
public:
void doSomething(InputObj* io) {
eA = io->a;
eB = io->b;
int something2 = eA+eB;
std::cout<<something2<<std::endl;
};
private:
int eA;
int eB;
};
class MainSolver{
// I have most things happening from here
public:
void start() {
//get inputs;
inputObj_ = new InputObj();
inputObj_ -> getInputs();
myA = inputObj_->a;
myB = inputObj_->b;
//do some solve:
int something = myA*myB;
//do some extrasolve
extraSolver_ = new ExtraSolver();
extraSolver_ -> doSomething(inputObj_);
};
private:
InputObj* inputObj_;
ExtraSolver* extraSolver_;
int myA;
int myB;
};
int main() {
MainSolver mainSolver;
mainSolver.start();
}
Summary of question: A lot of my objects need to use the same variables. Is my implementation the correct way of achieving this.
Don't use classes when functions will do fine.
Don't use dynamic allocation using new when automatic storage will work fine.
Here's how you could write it:
#include<iostream>
struct inputs {
int a;
int b;
};
inputs getInputs() {
return { 1, 2 };
}
void doSomething(inputs i) {
int something2 = i.a + i.b;
std::cout << something2 << std::endl;
}
int main() {
//get inputs;
inputs my_inputs = getInputs();
//do some solve:
int something = my_inputs.a * my_inputs.b;
//do some extrasolve
doSomething(my_inputs);
}
I'll recommend reading a good book: The Definitive C++ Book Guide and List
my answer would be based off your comment
"Yea I still haven't got the feel for passing objects around to each other, when it is essentially global variables im looking for "
so this 'feel for passing object' will come with practice ^^, but i think it's important to remember some of the reasons why we have OO,
the goal (in it simplified version) is to modularise your code so as increase the reuse segment of code.
you can create several InputObj without redefining or reassignig them each time
another goal is data hiding by encapsulation,
sometimes we don't want a variable to get changed by another function, and we don't want to expose those variable globally to protect their internal state.
for instance, if a and b in your InputObj where global variable declared and initialized at the beginning of your code, can you be certain that there value doesn't get changed at any given time unless you want to ? for simple program yes.. but as your program scale so does the chances of your variable to get inadvertently changed (hence some random unexpected behavior)
also there if you want the initial state of a and b to be preserved , you will have to do it yourself ( more temp global variables? )
you get more control over the flow of your code by adding level abstractions with classes/inheritances/operation overriding/polymorphisms/Abtract and interface and a bunch of other concepts that makes our life easier to build complex architectures.
now while many consider global variable to be evil, i think they are good and useful when used properly... otherwise is the best way to shoot yourself in the foot.
I hope this helped a bit to clear out that uneasy feeling for passing out objects :)
Is using your approach good or not strongly depends on situation.
If you need some high speed calculation you can't provide incapsulation methods for your InputObj class, though they are recommended, because it will strongly reduce speed of calculation.
However there are two rules that your can follow to reduce bugs:
1) Carefully using 'const' keyword every time you really don't want your object to modify:
void doSomething(InputObj * io) -> void doSomething(const InputObj * io)
2) Moving every action related with initial state of the object(in your case, as far as I can guess, your InputObj is loaded from file and thus without this file loading is useless) to constructor:
Instead of:
InputObj() { }
void getInputs(String filename) {
//reading a,b from file
};
use:
InputObj(String filename) {
//reading a,b from file
};
You are right that this way you have implemented global variables, but I would call your approach structured, and not complicated, as you encapsulate your global values in an object. This will make your program more maintainable, as global values are not spread all over the place.
You can make this even nicer by implementing the global object as a singleton (http://en.wikipedia.org/wiki/Singleton_pattern) thus ensuring there is only one global object.
Further, access the object through a static member or function. That way you don't need to pass it around as a variable, but any part of your program can easily access it.
You should be aware that a global object like this will e.g. not work well in a multithreaded application, but I understand that this not the case.
You should also be aware that there is a lot of discussions if you should use a singleton for this kind of stuff or not. Search SO or the net for "C++ singleton vs. global static object"

The usage of anonymous enums

What is the purpose of anonymous enum declarations such as:
enum { color = 1 };
Why not just declare int color = 1?
That's a so-called enum trick for declaring a compile-time integer constant. It's advantage is it guarantees that no variable is instantiated and therefore there's no runtime overhead. Most compilers introduce no overhead with integer constants anyway.
Enums don't take up any space and are immutable.
If you used const int color = 1; then you would solve the mutability issue but if someone took the address of color (const int* p = &color;) then space for it would have to be allocated. This may not be a big deal but unless you explicitly want people to be able to take the address of color you might as well prevent it.
Also when declaring a constant field in a class then it will have to be static const (not true for modern C++) and not all compilers support inline initialization of static const members.
Disclaimer: This answer should not be taken as advice to use enum for all numeric constants. You should do what you (or your co-workers) think is more readable. The answer just lists some reasons one might prefer to use an enum.
If this is old code, then enum might have been used for the "enum hack".
You can learn more about the "enum hack", for example, in this link: enum hack
In short: this allows defining the value once, just like #define or defining a variable, but unlike #define - here the compiler makes sure that the value is a number (int, r-value) and prevents you from doing all kinds of mischief that you can do with the precompiler's simple "search and replace", and unlike defining a variable - never takes up space under any compiler or configuration, and prevents changes to it (even const variables can sometimes be changed if you try hard enough).
(1) int color = 1;
color is changeable (accidently).
(2) enum { color = 1 };
color cannot be changed.
The other option for enum is,
const int color = 1; // 'color' is unmutable
Both enum and const int offer exactly same concept; it's a matter of choice. With regards to popular belief that enums save space, IMO there is no memory constraint related to that, compiler are smart enough to optimize const int when needed.
[Note: If someone tries to use const_cast<> on a const int; it will result in undefined behavior (which is bad). However, the same is not possible for enum. So my personal favorite is enum]
One use of this is when you're doing template metaprogramming, because enum objects are not lvalues, while static const members are. It also used to be a common workaround for compilers that didn't let you initialize static integral constants in the class definition. This is explained in another question.
When you use
enum {color = 1}
you're not using any memory it's like
#define color 1
If you declare a variable
int color=1
Then you're taking up memory for a value that's not to be changed.
Answer
Readability and performance.
Details are describbed as notes to examples below.
Use cases
Personal example
In Unreal Engine 4 (C++ game engine), I have following property (engine exposed member variable):
/// Floor Slope.
UPROPERTY
(
Category = "Movement",
VisibleInstanceOnly,
BlueprintGetter = "BP_GetFloorSlope",
BlueprintReadOnly,
meta =
(
ConsoleVariable = "Movement.FloorSlope",
DisplayName = "Floor Slope",
ExposeOnSpawn = true,
NoAutoLoad
)
)
float FloorSlope = -1.f;
This is a value of floor slope player is standing on (value ∈ [0; 90)°), if any.
Because of engine limitations, it cannot be neither std::optional nor TOptional.
I've came up with a solution to add another self explainable variable bIsOnFloor.
bool bIsOnFloor = false;
My C++ only internal setter for FloorSlope takes the following form:
void UMovement::SetFloorSlope(const float& FloorSlope) noexcept
contract [[expects audit: FloorSlope >= 0._deg && FloorSlope < 90._deg]]
{
this->bIsOnFloor = true;
this->FloorSlope = FloorSlope;
AUI::UI->Debug->FloorSlope = FString::Printf(L"Floor Slope: %2.0f", FloorSlope);
};
Adding special case where FloorSlope parameter would take argument of -1.f would be hard to guess and not user friendly.
Instead, I'd rather create False enum field:
enum { False };
This way, I can simply overload SetFloorSlope function that takes intuitive False instead of -1.f.
void UMovement::SetFloorSlope([[maybe_unused]] const decltype(False)&) noexcept
{
this->bIsOnFloor = false;
this->FloorSlope = -1.f;
AUI::UI->Debug->FloorSlope = L"Floor Slope: —";
};
When a player character hits a floor upon applying gravity to it on tick, I simply call:
SetFloorSlope(FloorSlope);
… where FloorSlope is a float value ∈ [0; 90)°.
Otherwise (if it does not hits a floor), I call:
SetFloorSlope(False);
This form (as opposed to passing -1.f) is much more readable, and self explanatory.
Engine example
Another example may be to prevent or force initialization.
Mentioned above Unreal Engine 4 commonly uses FHitResult struct containing information about one hit of a trace, such as point of impact and surface normal at that point.
This complex struct calls Init method by default, setting some values to certain member variables. This can be forced or prevented (public docs: FHitResult #constructor):
FHitResult()
{
Init();
}
explicit FHitResult(float InTime)
{
Init();
Time = InTime;
}
explicit FHitResult(EForceInit InInit)
{
Init();
}
explicit FHitResult(ENoInit NoInit)
{
}
Epic Games defines such enums similiar, but adds redundant enum names:
enum EForceInit
{
ForceInit,
ForceInitToZero
};
enum ENoInit {NoInit};
Passing NoInit to the constructor of FHitResult prevents initialization, what can lead to performance gain by not initializing values that will be initialized elsewhere.
Community example
FHitResult(NoInit) usage in DamirH's post on Comprehensive GameplayAbilities Analysis Series:
//A struct for temporary holding of actors (and transforms) of actors that we hit
//that don't have an ASC. Used for environment impact GameplayCues.
struct FNonAbilityTarget
{
FGameplayTagContainer CueContainer;
TWeakObjectPtr<AActor> TargetActor;
FHitResult TargetHitResult;
bool bHasHitResult;
public:
FNonAbilityTarget()
: CueContainer(FGameplayTagContainer())
, TargetActor(nullptr)
, TargetHitResult(FHitResult(ENoInit::NoInit))
, bHasHitResult(false)
{
}
// (…)
I dont see it mentioned, another use is to scope your constants. I currently work on code that was written using Visual Studio 2005, and it is now ported to android - g++. In VS2005 you could have code like this enum MyOpts { OPT1 = 1 }; and use it as MyOpts::OPT1 - and compiler did not complain about it, even though it is not valid. g++ reports such code as error, so one solution is to use anonymous enum as follows: struct MyOpts { enum {OPT1 =1}; };, and now both compilers are happy.