This is just going to be a bunch of interesting and sometimes useful tricks, hacks and tidbits about C++
INFINITY
This is in windows SDK.
In corecrt_math.h #define _HUGE_ENUF 1e+300 // _HUGE_ENUF*_HUGE_ENUF must overflow #define INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF))
I don’t know, I just like that.
Change Detector
Need to check if anything changed in the editor?
You could write:
bool changed = false; changed = ImGui::Checkbox(...) && changed; changed = ImGui::Checkbox(...) && changed;
But this is kind of ugly and confusing. So, use change detector:
Change::ChangeDetector::ChangeDetector()
: value_(false) {}
Change::ChangeDetector& Change::ChangeDetector::operator=(bool aBool)
{
if (aBool)
value_ = aBool;
return *this;
}
Change::ChangeDetector::operator bool()
{
return value_;
}
void Change::ChangeDetector::Reset()
{
value_ = false;
}
It becomes:
ChangeDetector changed;
changed = ImGui::Checkbox(...);
changed = ImGui::Checkbox(...);
if (changed)
...
User-Defined Literals
If you’ve learned about operator overloading already, time for the bananas crazy version of it. You can define unary operators much like how std::chrono does with things like ms (milliseconds) and s (seconds).
The following example creates an operator that works on integers and just doubles them. The standard requires it to be that silly data type.
constexpr int operator""_doubleit(unsigned long long int val)
{
return val * 2;
}
int main()
{
std::cout << 5_doubleit << std::endl;
return 0;
}
This outputs 10.
Now you too can have a microfortnight in your game!
Swallowing the Semi-Colon and Backslashes
Sometimes you’re writing a macro and it gets a bit long:
#define BigMacro(a, b) if (a > b) { std::cout << "a was bigger than b" << std::endl; LogMessage("Yikes"); } else { LogMessage("We're all good now");}
So, use the backslash to continue onto the next line:
#define BigMacro(a, b) \
if (a > b) \
{ \
std::cout << "a was bigger than b" << std::endl; \
LogMessage("Yikes"); \
} \
else \
{ \
LogMessage("We're all good now"); \
} \
If you were to actually use this, adding the semi-colon isn’t necessary. IntelliSense doesn’t like that very much. So, we’re going to swallow the semi-colon!
#define BigMacro(a, b) \
do { \
if (a > b) \
{ \
std::cout << "a was bigger than b" << std::endl; \
LogMessage("Yikes"); \
} \
else \
{ \
LogMessage("We're all good now"); \
} \
while (0)
No less efficient. Forces the user to put a semi-colon. Plays nicer with other if statements. Perfect.
Stringifying and Useful Defines
Sometimes you want to put offending erroring code into the log message to help debug it. The example below takes in some code and checks if it is not 0 (0 being a common value to mean that no error occurred). If it fails, it prints out a bunch of debug text!
#include <iostream>
#define CHECK(code) \
if (code != 0) \
{ \
std::cout << std::string(#code) \
<< " Failed on line " \
<< __LINE__ \
<< " in function " \
<< __FUNCTION__ \
<< " in file " \
<< __FILE__ \
<< std::endl; \
}
int main()
{
CHECK(5 + 7); // Line 18
return 0;
}
This code will output:
” 5 + 7 Failed on line 18 in function main in file main.cpp”
Token Pasting
Oh look, more macro madness.
#define MAKE_FUNCTION(Name, someConstant) \
void DoSomething_##Name(int value) \
{ \
return value + someConstant; \
}
The ## in this code will take whatever you handed the MAKE_FUNCTION macro and put it into the function name when it compiles. So this:
MAKE_FUNCTION(Toaster, 5);
Turns into this:
void DoSomething_Toaster(int value)
{
return value + 5;
}
Alright, that’s enough. Time to learn about code reviews.
HEY. I gave you a lot in this one. We’re learning about code reviews. Deal with it.