Could we put const at the top of the file and why constexpr?

I use to do Unity (C#) before starting this course and I put all my const at the top of my classes.

I personally find it really useful to have all your const at the top of your file, since it allows me to not have to do any research to change a simple value. For example, I open the file containing the logic of my game and, before all my methods, there is a MAX_TRY_NBR = 6, that I can simply change and it’s done!

Could it be done here?

Could it be just under of
FBullCowGame BCGame;

And for the Game logic, could it be inside the private section of the header?

Finally, I’m not completely sure that I understand the difference between const and constexpr. What I understand is that constexpr is knowed at compile time, but if so, why are we using it? Why would want one of our const to be knowed at compile time?

1 Like

Let’s go one at a time:

Can a constant be declared in the same file as it is used (referring to your MAX_TRY_NBR example)?

Yes, that was what Ben was talking about in one of the first C++ videos: The header files are essentially optional, but you should still use them because C++ needs to know about functions before they are called, so either the declaration has to be above the first call, or you have to declare the function as a prototype.
Since multiple files might use the same functions, you’d have to copy-paste the same prototypes into many different files. If you use .h files, then you can just include the respective .h file and you don’t have to worry about keeping every prototype up to date in a dozen different files.

const Vs constexpr:
You read the docs, so here here’s the reasoning behind it as I understand it:
There is a simple rule of thumb: If you think you can make something very strict, do it. You can always change it to be more permissive later when you need it. I read somewhere that you should make all methods private until you know you need to access them from outside.

2 Likes

Thanks for your reply, but none of your answers seem to actually answer any of my questions. Sorry if it’s just me not understanding you.

Hmm, ok, I can see that my previous answer is not particularly clear, sorry.
Let me try again:

First question
Yes, you can declare MAX_TRY_NBR in the same file as the rest of your code. It’s as simple as moving the declaration from your .h file to the top of your .cpp file. If you are positive that you won’t be using the same const in other files, go for it! But if you need access to the MAX_TRY_NBR in other files / classes you have two options:

  • Copy the MAX_TRY_NBR declaration into every .cpp file where you need it (don’t do that, prone to errors and misery)
  • write a .h file with MAX_TRY_NBR once and #include it everywhere you need it

Second question
I found this explanation for const Vs constexpr and I think it’s quite good and hands-on with an example: https://forums.unrealengine.com/development-discussion/c-gameplay-programming/29426-const-vs-constexpr

The important difference, as you said yourself, is constexpr is evaluated at compile-time whereas const is evaluated at run-time.

compile-time = when the compiler creates the binary
run-time = when the binary is executed

With compile-time evaluation, the resulting binary will not contain any logic, just a number (or string or whatever). That’s the most optimised thing you can get (only works this way if you use the “Release” build option, if you use debug, there is no difference in the binary between constexpr and const, I actually had a look at the assembly output to find that out).
With run-time evaluation, the binary will contain logic and your const statement will be executed, but it can only be executed once for a variable declaration, otherwise you get an error.

Example:

#include <iostream>
#include <string>

int main()
{
	int constexpr ONE = 1;
	std::cout << "ONE: " << ONE << std::endl;

	// we can do maths with constants, as long as they can be evaluated at compile time
	int constexpr FIVE = (400 / 8) / 10;
	std::cout << "FIVE: " << FIVE << std::endl;

	// we don't know at compile time what the user will type,
	// this can be different every time you start the program
	std::string UserInput = "";
	std::cout << "Type something that will then be set to the constant INPUT_ONCE: ";
	// side note: we have to use a variable that can be changed for getline() to work,
	// that's why we don't set INPUT_ONCE directly
	std::getline(std::cin, UserInput);

	// although we don't know which value will be in INPUT_ONCE,
	// we know that it won't change during the program's running time
	// because we set it to const
	std::string const INPUT_ONCE = UserInput; // try changing this to constexpr
	std::cout << "INPUT_ONCE :" << INPUT_ONCE << std::endl;

    return 0;
}

I hope this time my answer is clearer.

Also, thanks for asking this question, you made me look into the difference of const vs constexpr quite thoroughly :slight_smile:

Thank you for your answer and sorry for the late reply.

Just to be sure that I got it, constexpr will result in a value in the binary (would that also make the code faster?) and const will result in some kind of value that will need to be reevaluated during run time?

Also, I headed a feature to randomly select the hidden word by having a set of possible words in a const. I would like to have your opinion on where I put my const variable:

private:
	int32 MyCurrentTry;
	FString MyHiddenWord;
	bool bGameIsWon;

	FString SelectRandomIsogram();
	bool IsIsogram(FString) const;
	bool IsLowercase(FString) const;

	const FString POSSIBLE_ISOGRAMS[10] = { "planet", "sun", "orgasm", "duck", "block", "same", "dance", "father", "flower", "two" };

About const and constexpr: Yes, you’re exactly right!

About where to put your array of isograms:
Making it a private class variable seems like the right way to go to me! :+1:

Alternatively you could put the array directly into the SelectRandomIsogram() method if you wanted to, because it’s the only function that’s using the array. But personally I wouldn’t do that because I feel like I want data and constants on the object rather than ecapsulating them in a method. But I’m not entirely sure about that, it’s more like an aesthetic choice to me.

Btw, your guess is as good as mine, I’m a C++ noob :slight_smile:

I’ve moved this to the new #unreal:ask sub-forum which has a “Solution” function, and @DanM will be swinging-by

1 Like

This is incorrect. constexpr means that the variable/function can be evaluated at compile time, it’s not guaranteed that it necessarily will be.

Similarly const doesn’t mean it will be evaluated at run-time.

const int val = 5 * 5;

is a constant expression and val would be 25 and no calculation of 5*5 would be done at run-time. https://godbolt.org/z/90pTqc

Also incorrect. https://godbolt.org/z/KZctLy. It’s the same if you enable optimisations or not. These examples are too trivial for the compiler.


So constexpr for a variable means that it can be evaluated at compile time and is implied to be const.

#include <array>
int square(int n) { return n * n; }
int main()
{
    //compiler error, square is a non-constexpr function.
    constexpr int val = square(5); 
    //okay so far
    const int val2 = square(3);
    //error test was initialised with a non-constexpr value
    std::array<int, val2> test;
}
  • val is a compile time error as it’s marked as constexpr but it’s calling a non-constexpr function.
  • val2 is fine, it’s a const int and initialised to square(3) however it’s then used in an expression where only compile-time constants can be used (template argument) so test is a compile time error.

Making square constexpr will resolve both issues.

2 Likes

FYI our helpful? bot will keep bumping this until somebody marks it as solved :wink:

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms