2

例如,考虑以下存在 name 冲突的情况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>?
  • 编译器如何知道是否bar需要nest1<W>cls::nest1<W>我们是否不使用cls::(例如bar(cls::nest1<W> x))作为前缀?
  • cls::无论如何显式前缀是一种好习惯吗?

注意:编译器实际上选择隐式声明 bar(cls::nest1<W> x)

4

1 回答 1

0

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

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

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

然后在§3.4.1 [basic.lookup.unqual] p8(不合格的名称查找,例如没有::):

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

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

(我的示例中的声明符 IDfooand bar。)

于 2013-05-11T14:55:22.780 回答