Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why function default parameters cannot be perferct forwarded in C++?

I found quite weird behavior from my perspective: function default arguments cannot be forwarded in code bellow.

void Test(int test = int{}) {}

template<typename F, typename ...Args>
void Foo(F&& f, Args&&... args)
{
    std::forward<F>(f)(std::forward<Args>(args)...);
}

int main()
{
    Foo(Test, 0); // This compiles
    Foo(Test);    // This doesn't compile
}

Clang reports: error: too few arguments to function call, expected 1, have 0 GCC and VC report same errors.

Can anybody explain it?

Code is here: http://rextester.com/live/JOCY22484

like image 591
Viktor Avatar asked Jul 12 '17 22:07

Viktor


People also ask

Can all the parameters of a function can be default parameters?

All the parameters of a function can be default parameters.

Which function Cannot have default parameters?

Constructors cannot have default parameters.

Does C allow default parameters?

There are no default parameters in C. One way you can get by this is to pass in NULL pointers and then set the values to the default if NULL is passed.

How C function parameters arguments are passed by default?

Default Arguments in C++ A default argument is a value provided in a function declaration that is automatically assigned by the compiler if the calling function doesn't provide a value for the argument. In case any value is passed, the default value is overridden.


1 Answers

Test is a function that always takes one argument. If its declaration with the default argument is visible when Test is invoked by name, the compiler will implicitly add the default argument to the call. However, once Test has been converted into a pointer or reference to function, the default argument information is no longer visible.

This can be worked around by creating a functor which really does take zero or one arguments and has that information encoded into its type so it cannot be destroyed, like so:

struct Test {
    void operator()(int) { /* ... */ }
    void operator()() { operator(int{}); }
} test;
// ...
Foo(test, 0); // ok
Foo(test);    // ok
like image 141
Brian Bi Avatar answered Sep 28 '22 12:09

Brian Bi