-3

According to the C++ 17 Standard (10.3.3 The using declaration)

1 Each using-declarator in a using-declaration98 introduces a set of declarations into the declarative region in which the using-declaration appears.

and

10 A using-declaration is a declaration and can therefore be used repeatedly where (and only where) multiple declarations are allowed.

and (The C++ 17 Standard, 11.3.6 Default arguments)

  1. ...When a declaration of a function is introduced by way of a using-declaration (10.3.3), any default argument information associated with the declaration is made known as well. If the function is redeclared thereafter in the namespace with additional default arguments, the additional arguments are also known at any point following the redeclaration where the using-declaration is in scope.

So this program

#include <iostream>

void f( int x, int y = 20 )
{
    std::cout << "x = " << x << ", y = " << y << '\n';
}

int main() 
{
    using ::f;
    void f( int, int );
    
    f( 10 );
    
    return 0;
}

as expected compiles and outputs

x = 10, y = 20

In fact it is similar to the program

#include <iostream>

void f( int x, int y )
{
    std::cout << "x = " << x << ", y = " << y << '\n';
}

int main() 
{
    void f( int, int = 20 );
    void f( int, int );
    
    f( 10 );
    
    return 0;
}

Now it would be logical consistent that the following program also was valid.

#include <iostream>

void f( int x, int y = 20 )
{
    std::cout << "x = " << x << ", y = " << y << '\n';
}

int main() 
{
    using ::f;
    
    void f( int, int );

    f( 10 );
    
    void f( int = 10, int );
    
    f();
    
    return 0;
}

However this program does not compile.

On the other hand, consider the following program.

#include <iostream>

namespace N
{
    int a = 10;
    int b = 20;
    
    void f( int, int = b );
}

int a = 30;
int b = 40;

void N::f( int x = a, int y )
{
    std::cout << "x = " << x << ", y = " << y << '\n';
}

int main() 
{
    using N::f;
    
    f();
    
    return 0;
}

It compiles successfully and its output is

x = 10, y = 20

So could be the same principles applied to functions introduced by the using declaration?

What is the reason of that such an addition of default arguments is not allowed?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335

2 Answers2

3

You can only declare new default arguments in the same scope as the original declaration. using does not change this.

For non-template functions, default arguments can be added in later declarations of a function in the same scope.

dcl.fct.default/4

Caleth
  • 52,200
  • 2
  • 44
  • 75
  • Reread my question. Your answer is irrelevant. – Vlad from Moscow Apr 08 '21 at 12:21
  • @VladfromMoscow Found where the standard prohibits this. – Caleth Apr 08 '21 at 12:33
  • `using` changes behavior of gcc/msvc in [that case](https://godbolt.org/z/vsM5M9555) :-/ – Jarod42 Apr 08 '21 at 12:39
  • 1
    @Jarod42 msvc rejects any default parameters introduced in the `using` scope, which I read as the correct behaviour here – Caleth Apr 08 '21 at 12:40
  • @Caleth As I already pointed you answer is irrelevant and does not make a sense in the context of the question. Remove it. – Vlad from Moscow Apr 08 '21 at 13:01
  • @VladfromMoscow how is "the standard only permits it in a particular case" not relevant? – Caleth Apr 08 '21 at 13:08
  • @Caleth Can you understand what is written in the question?! What you wrote I know without you. The question is about why the Committee excluded such a possibility described in my question. What was the reason that it decided to exclude such a possibility. – Vlad from Moscow Apr 08 '21 at 13:17
  • 1
    @VladfromMoscow I wasn't there when the wording was written, but "no-one specified / implemented it" is the default answer to "why does $language lack $feature" – Caleth Apr 08 '21 at 13:24
  • @VladfromMoscow: I also read your question as "which part of standard disallow that construct?" and not as "Why standard is written like that?". For the former , whereas first version of answer was incorrect, that one makes sense. For the later, harder to answer (and NathanOlivier's answer isn't the why neither, but *"interpreting"* provided quote). – Jarod42 Apr 08 '21 at 16:02
2

I believe

any default argument information associated with the declaration is made known as well

doesn't mean the arguments are actually imported into the scope, it's just known that they do exist and can be used.

That would mean that void f( int = 10, int ); isn't adding to void f( int x, int y = 20 ), but is instead trying to add to void f( int, int ); which would be illegal as there isn't a default argument for the second parameter in the scope that the using declaration is in.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402