【问题标题】:The using declaration and function default argumentsusing 声明和函数默认参数
【发布时间】:2021-07-04 07:33:02
【问题描述】:

根据 C++ 17 标准(10.3.3 using 声明)

1 using-declaration98 中的每个 using-declarator 都引入了一组 声明进入声明区域,其中 using-declaration 出现。

10 using-declaration 是一个声明,因此可以使用 重复在哪里(并且仅在哪里)允许多个声明。

和(C++ 17 标准,11.3.6 默认参数)

  1. ...当函数声明通过 using-declaration (10.3.3),任何默认参数信息 与该声明相关的信息也被告知。如果函数 此后在命名空间中重新声明,具有额外的默认值 论点,附加论点在任何时候也是已知的 在使用声明在范围内的重新声明之后。

所以这个程序

#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;
}

按预期编译和输出

x = 10, y = 20

其实和程序差不多

#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;
}

现在逻辑一致,以下程序也是有效的。

#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;
}

但是这个程序不能编译。

另一方面,考虑以下程序。

#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;
}

编译成功,输出为

x = 10, y = 20

那么,同样的原则可以应用于 using 声明引入的函数吗?

不允许这样添加默认参数的原因是什么?

【问题讨论】:

  • @NathanOliver 这是合理的。我没有想过这个。写一个答案。
  • 已添加。我们会看看人们的想法。
  • 当默认值仅在本地范围内时编译器不同意Demo...

标签: c++ c++17 function-declaration default-arguments using-declaration


【解决方案1】:

您只能在与原始声明相同的范围内声明新的默认参数。 using 不会改变这一点。

对于非模板函数,可以在相同范围内的函数声明中添加默认参数。

dcl.fct.default/4

【讨论】:

  • 重读我的问题。你的回答无关紧要。
  • @VladfromMoscow 发现标准禁止这样做。
  • using 更改that case 中 gcc/msvc 的行为:-/
  • @Jarod42 msvc 拒绝在using 范围内引入的任何默认参数,我在这里将其视为正确的行为
  • @VladfromMoscow 编写措辞时我不在场,但“没有人指定/实施它”是“为什么 $language 缺少 $feature”的默认答案
【解决方案2】:

我相信

与声明相关的任何默认参数信息也会被公开

并不意味着参数实际上被导入到作用域中,只是知道它们确实存在并且可以使用。

这意味着void f( int = 10, int ); 没有添加到void f( int x, int y = 20 ),而是试图添加到void f( int, int );,这将是非法的,因为在该范围内没有第二个参数的默认参数using 声明在。

【讨论】:

    猜你喜欢
    • 2016-07-03
    • 1970-01-01
    • 2014-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多