Dereferencing a function with default arguments - C++14 vs C++11
Asked Answered
N

2

20

Following code can't be compiled with g++ version 5.4.0 with option -std=c++1y:

void f(int=0) ;

int main() {
    f(); // ok
    (*f)(2);// ok
    (*f)();// ok c++11; error with c++14: too few arguments to function
    return 0;
}

The function declared to have default argument, so what is wrong here? thanks for help.

And why does g++ -c -std=c++11 compile?

Numbat answered 30/10, 2017 at 10:48 Comment(3)
The obvious answer is to try a newer g++ version. The 5 line is old, and 5.4 isn't even its newest minor release. It's also prudent to search the GCC Bugzilla in cases like this, as the issue is probably already known, but filtering through to older versions can take a while and sometimes just doesn't happen.Poser
Seems like a compiler bug. Clang rejects this code both as C++11 and C++14.Endow
Could this be related to the order of optimisation passes? i.e. the function pointer optimised to a direct call before the arguments are processedPoser
E
25

Accepting (*f)() as valid is a GCC bug. The letter of the standard indicates that using a function name with unary * should cause the function name to decay into a pointer. The pointer should then be dereferenced to obtain the functions address for the call expression.

But GCC seems clever, and omits the above behavior. It treats (*f) simply as f. And calling f can be done with default arguments.

However, one can force GCC to preform the decay. Unary + applied on the function name will decay it to a pointer forcefully. So the following two:

(+f)();
(*+f)();

Cause GCC to emit error: too few arguments to function on either standard revision, in both GCC 7.2 and GCC 6.3.

Endow answered 30/10, 2017 at 11:42 Comment(4)
Above @StoryTeller stated Clang rejected the OP code in C++11 and C++14. Does Clang have the same bug?Bohunk
@Bohunk - I'm StoryTeller. And Clang rejects the original code, as it should. It doesn't bug out here.Endow
Visual Studio 2017 happily accepts the original code. Both (+f)() and (*+f)(), as well as (+*f)() -- all result in internal compiler error.Tutelage
@AlexanderGutenev - Consistency is important :) I'm amazed that MSVC bungles this up. The specification of unary + is dead simple...Endow
T
8

Default arguments are not a part of function type, so they are discarded when you implicitly convert function to function pointer and then indirect that pointer.

Tutelage answered 30/10, 2017 at 10:51 Comment(7)
then why does g++ -c -std=c++11 compile?Numbat
I'm not sure, I think it should not compile either.Tutelage
even more. it compiles with g++-6 for -std-c++14.Numbat
@DaanTimmer - ideone doesn't show compiler options, in particular the standard revision flag. What does your link prove?Endow
@StoryTeller Yes it does, in the sidebar on the right, near the middle vertically: Language: C++14 (gcc 6.3)Poser
@Poser - Then I stand corrected. That link proves GCC's bug has become worse.Endow
And my test on coliru with GCC 7.2 demonstrates the bug is still there.Endow

© 2022 - 2024 — McMap. All rights reserved.