【问题标题】:Who is correct here, GCC or MSVC?谁是正确的,GCC 还是 MSVC?
【发布时间】:2016-11-18 10:31:43
【问题描述】:

假设我们有这样的结构:

namespace some_namespace::types {
    using foo_t = int;
}

namespace some_namespace::classes {
    class bar {
    public:
        auto do_stuff() -> types::foo_t;
    };
}

using namespace some_namespace::classes;

auto bar::do_stuff() -> types::foo_t {
    return 1;
}

这段代码在 GCC6 中编译愉快。
另一方面,启用/std:c++latest 开关的VS15 无法识别do_stuff 的返回类型。它返回C2653

现在,我非常怀疑的是,通过将下半部分更改为以下内容可以解决此问题:

using namespace some_namespace;

auto classes::bar::do_stuff() -> types::foo_t {
    return 1;
}

在我看来应该是平等的。我是否误以为这是一个 MSVC 错误?标准对此有何规定?

【问题讨论】:

  • 不只是 GCC 和 MSVC 以不同的速率和不同的优先级实施新标准。
  • the standard 中的 nested-name-specifier 上找不到任何关于将其命名空间带入 using 命名空间的信息,但它在 somewhere 那里。
  • 诚然,我还没有详细阅读嵌套命名空间规范,但我希望这不应该编译。使用子命名空间不应使用其父命名空间。那么编译器怎么知道types::foo_t在函数定义中真的意味着some_namespace::types::foo_t呢?
  • @NicolBolas [basic.lookup.unqual]/8。 declarator-id 之后的名称被查找,就好像它们在成员函数体中一样,即首先在类中,然后在类的封闭命名空间中。

标签: c++ visual-studio gcc namespaces name-lookup


【解决方案1】:

这与 C++17 特性无关,它没有触及 using-directives,也根本与 using-directives 无关。 MSVC 从

产生同样的错误
namespace some_namespace{
    namespace types {
        using foo_t = int;
    }
    namespace classes {
        class bar {
        public:
            auto do_stuff() -> types::foo_t;
        };
    }
}

using some_namespace::classes::bar;

auto bar::do_stuff() -> types::foo_t {
    return 1;
}

[basic.lookup.unqual]/8:

对于X 类的成员,在定义中使用的名称 [...] X 定义之外的类成员,遵循 成员的declarator-id,应在以下之一中声明 方式:

  • 在其用于使用它的块或封闭块([stmt.block])之前,或

  • 应为X 类的成员或X ([class.member.lookup]) 基类的成员,或

  • [...省略了关于嵌套类和本地类的两个要点...]

  • 如果 X 是命名空间 N [...] 的成员,则在使用名称之前,在命名空间 NN 的封闭命名空间之一中。

types 的名称查找应首先在 bar 内部查找,然后在 classes 内部查找,然后在 some_namespace 内部查找。最后一个应该找到命名空间types

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-21
    • 2016-10-20
    • 2021-12-19
    • 1970-01-01
    • 2021-04-14
    • 1970-01-01
    相关资源
    最近更新 更多