c++ - 相同类型重新定义的 Clang typedef(和别名)导致意外错误

标签 c++ c++11 templates clang++

代码

template <typename T, typename Y>
class B;

template <typename T, typename Y>
class A {
public:
  typedef B<T, Y> handle;

  void func(B<T, Y> &arg);
};

template <typename T, typename Y>
class B {
public:    
  typedef B<T, Y> handle;

private:
  int i;

public:
  // friend void A<T,Y>::func(B<T, Y>& arg); //builds
  friend void A<T, Y>::func(handle &arg); // builds with alias in A *not* defined, otherwise fails.
};

template <typename T, typename Y> void A<T, Y>::func(B<T, Y> &arg) {
  arg.i = 9;
}

int main() {
    B<int, int> b;
    A<int, int> a;
    a.func(b); // error
}

错误

main.cpp:31:7: error: 'i' is a private member of 'B<int, int>'
  arg.i = 9;
      ^
main.cpp:38:5: note: in instantiation of member function 'A<int, int>::func' requested here
  a.func(b);
    ^
main.cpp:23:7: note: declared private here
  int i;
      ^
1 error generated.

问题

我试图让我公司的代码在 clang 下构建,并遇到了这种情况。该代码在 GCC 5 - 8 下构建。我试图找到一个描述这种情况的规则,但结果是空的。修复(或变通方法)很明显,但我正在寻求对正在发生的事情的澄清,以更好地理解这种情况。

所以这两个类都将相同的 typedef 定义为相同的类型(也尝试使用别名,结果相同)。如果将 typedef 用作友元声明的类型,则会出现上述错误,但有一个异常(exception)。当 typedef 出现在 A 中但出现在 B 中时。 如果您删除模板,它也会构建。

感谢您的任何见解!

最佳答案

这大概是 CWG 1906 .基本上,clang 实现了标准中的实际措辞——这没有多大意义。

基本上,考虑这个例子,由 Richard Smith 提供:

namespace A { 
  struct X { void f(int); }; 
} 
namespace B { 
  using type = int; 
  struct Y { 
    friend void A::X::f(type);
  }; 
} 

type 的标准查找顺序曾经是 A::XB::YB::。 Clang 做了 A::XA::B::YB::。 gcc 执行了 A::XB::YA::

现在,标准的查找顺序与我们在 Y 的上下文中一样:

for a friend declaration in a class Y, in a scope that would be searched for a name appearing within Y.

B::YB:: 我们从不考虑 A。换句话说,对于您的原始示例,将找到(根据需要)B::handle,而不是 A::handle

关于c++ - 相同类型重新定义的 Clang typedef(和别名)导致意外错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51849707/

相关文章:

c++ - 函数不写入 txt 文件

c++ - 我怎么能给c++ vector赋值

c++ - CERN ROOT 的对象所有权和 C++11 智能指针

c++ - 通过参数字符串化宏调用模板函数?

c++ - 在 C++ 中释放动态分配内存的问题

c++ - 从 C++ 宏中删除额外的括号

独立访问器/修改器接口(interface)的 C++ 设计模式

c++ - 从 vector<BSTR> 获取指向 BSTR 的指针

c++ - c++ 有等效的 boost::numeric_cast<DestType>(SourceType) 吗?

c++ - 引用模板c++