With your code the way it currently is, I tested it on Compiler Explorer using various compilers...
Here are the results of 3 different compilers, their generated assembly, and possible errors or warnings. All compiler options are set to -std=c++17 -O3.
x86-64 clang(trunk)
asm
main: # @main
xor eax, eax
ret
Warnings-Errors
warning: empty parentheses interpreted as a function
declaration [-Wvexing-parse]
where a(); is highlighted as the warning in question
x86-64 gcc (trunk)
Fails to compile!
Warnings-Errors
error: declaration of 'Game*' Actor::Game()' changes meaning of
'Game' [-fpermissive]
where Game() is highlighted as the error in question
x64 msvc v19.24
asm
main PROC
xor eax, eax
ret 0
main ENDP
Warnings-Errors
warning C4930: 'Actor a(void)': prototyped function not called
(was a variable definition intended?)
where Actor a(); is highlighted as the warning in question
These are the results based on your current code. Now let's look at these 3 same examples but modifying just one little piece of your code...
I'm going to change Actor a(); in your main function to Actor a{}; instead and let's look at the differences...
x86-64 clang(trunk)
asm
main: # @main
xor eax, eax
ret
Warnings-Errors
None!
x86-64 gcc (trunk)
Fails to compile!
Warnings-Errors
error: declaration of 'Game*' Actor::Game()' changes meaning of
'Game' [-fpermissive]
where Game() is highlighted as the error in question.
x64 msvc v19.24
asm
a$ = 0
main PROC
$LN3:
push rdi
sub rsp, 16
lea rax, QWORD PTR a$[rsp]
mov rdi, rax
xor eax, eax
mov ecx, 8
rep stosb
xor eax, eax
add rsp, 16
pop rdi
ret 0
main ENDP
Warnings-Errors
None!
Assessment
If you compare the 3 you will see that both Clang and MSVC will compile in both situations, however, they will both give a warning for the first case and will compile without error for the second. GCC, on the other hand, fails to compile in both cases and generates the same exact warning or compiler error.
In the first case which is your original source, Clang and MSVC are able to determine that you meant to call the constructor of said class Actor but generates a warning message where GCC fails to compile it all together while using the () operator. GCC can not determine if you meant to call Actor::Game() or Game::Game().
We can also reason that both Clang and MSVC are pointing their warnings from the first case at a() while GCC is pointing its error at Game() in both cases.
To inspect what is going on even more, in the first case, both Clang and MSVC are generating almost identical assembly. In the second case, Clang is still generating the same assembly, but MSVCfootprint tells a completely different story!
What I can say from my current knowledge without doing any more research, based on the comparisons between
Actor a();
and
Actor a{};
and the behavior that I'm seeing from the generated warnings, errors, and assembly code is this...
I believe that it might be Implementation Defined across the different compilers.
I can not say if this is UB or not, but I would probably suspect that it could be in some cases in which you can see from the generated assembly, warnings, and errors above...
If you are using the () operator for the class's constructor, then there is at least some ambiguity within all three compilers. GCC doesn't even compile and generates an error. Clang and MSVC both compile where Clang gives the warning that the empty parenthesis is interpreted as a function declaration and MSVC gives the warning that the prototyped function was not called.
Yet when we switch to the {} operator or initializer list... Clang generates the same assembly that it did before but no longer generates a warning. MSVC gives a thorough set of instructions to where it appears that both classes are being constructed and generates no warning. GCC craps out in both situations and says, "I give up on your intentions" here's my error message always pointing at Game()!
Conclusion
So to answer your question:
Why can't function name be the same as return name type?
Depending on the context of use and the compiler that is being used it could be the same, and for other compilers, they may or will reject it.
So who's to say which compiler's interpretation is accurate and correct... I don't have a copy of the standard so I can not dive any further into the language-lawyer part of this, but I can generalize what is happening and why it is happening as I have just demonstrated.
I hope that this reasoning might help you within the naming conventions and how the compilers try to interpret such names and symbols while trying to turn them into objects.
So there may be some ambiguity in some contexts and no ambiguity in others. This leads me to believe this is implementation-defined across compilers since AFAIK the standard doesn't require a specific notation of name-reuse and that this could lead to UB! Therefore, this would not be good practice and definitely a code smell!
And all of this is agnostic of the hardware architecture too!