【问题标题】:Do we need to prefix member arguments of nested type with "::"?我们需要在嵌套类型的成员参数前加上“::”吗?
【发布时间】:2013-05-11 01:56:25
【问题描述】:

例如,考虑以下情况,其中存在名称冲突 nest1

template <typename U> class nest1 {};

class cls {
public:
    template <typename V> class nest1 {};

    template <typename W> class nest2 {
    public:
        void bar(nest1<W> x);
    };
};

template <typename W>
void cls::nest2<W>::bar(nest1<W> x) {}  // how does compiler know which nest<1>?
  • 如果我们不以cls:: 为前缀(例如bar(cls::nest1&lt;W&gt; x)),编译器如何知道bar 是采用nest1&lt;W&gt; 还是cls::nest1&lt;W&gt;
  • 无论如何,明确地为cls:: 加前缀是一种好习惯吗?

注意:编译器实际上选择隐式声明 bar(cls::nest1&lt;W&gt; x):

【问题讨论】:

  • 同名的全局变量和静态数据成员相同。
  • 所以它只是剥离层并在最近的父/祖先类中找到所需的声明?
  • 哦,我以为它会选择全局的。您可能应该在问题中指定这一点。

标签: c++ class templates nested


【解决方案1】:

在成员函数名之后使用的每个名称也在其类的词法范围内查找。这会导致以下(看似)不一致的行为,因为正常的返回类型是 not 在类的词法范围内:

struct X{
  struct Y{};

  Y foo(Y);
  Y bar(Y);
};

// normal return type is before 'foo', needs explicit scope qualification
// parameter doesn't (after 'foo')
X::Y X::foo(Y y){ return y; }

// trailing-return-type also doesn't (after 'bar')
auto X::bar(Y y) -> Y{ return y; }

对于这个的标准,我们看§9.3 [class.mfct] p5

如果成员函数的定义在其类定义之外,则成员函数名应使用:: 运算符由其类名限定。 [ 注意: 在成员函数定义中使用的名称(即在 parameter-declaration-clause 中包括默认参数(8.3. 6) 或在成员函数体中) 按照 3.4 中的描述进行查找。 —尾注 ] [...]

然后在§3.4.1 [basic.lookup.unqual] p8(非限定名称查找,例如没有::):

在类X的成员函数(9.3)的定义中使用的名称遵循函数的declarator-id31 [ ...] 应以下列方式之一声明:

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

(在我的示例中,declarator-idsfoobar。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-05
    • 2020-09-12
    • 2013-10-22
    • 2021-05-25
    • 1970-01-01
    • 2013-05-28
    相关资源
    最近更新 更多