【问题标题】:templated friend function lookup模板化友元函数查找
【发布时间】:2013-03-22 15:57:45
【问题描述】:

下面的简单代码编译正常

class A {
  int x[3];
public:
  A() { x[0]=1; x[1]=2; x[2]=3; }
  friend int const&at(A const&a, unsigned i) noexcept
  {
    return a.x[i];
  }
  friend int foo(A const&a, unsigned i) noexcept
  {
    int tmp = at(a,i);
    return tmp*tmp;
  }
};

但如果朋友是模板

class A {
  int x[3];
public:
  A() { x[0]=1; x[1]=2; x[2]=3; }

  template<unsigned I>
  friend int const&at(A const&a) noexcept
  {
    static_assert(I<3,"array boundary exceeded");
    return a.x[I];
  }

  template<unsigned I>
  friend int foo(A const&a) noexcept
  {
    int tmp = at<I>(a);   // <- error: use of undeclared identifier 'at'
    return tmp*tmp;
  }
};

查找规则发生变化,clang 抱怨说错误,但 gcc 和 icpc 没有。谁是对的(C++11)?以及如何为 clang 修复代码?

【问题讨论】:

  • 将函数声明为friend 有什么原因吗?
  • 试试::at&lt;I&gt;(a),但你不应该这样做。
  • @JoachimPileborg 当然(这里的代码只是一个简单的例子,可能不存在这样的原因),这就是问题的重点。
  • at 需要在周围的命名空间中声明。没有一个的友元函数只能通过 ADL 找到,而当您显式指定模板参数 IIRC 时,这还不会发生。
  • @Dave 不,没有帮助。

标签: c++ templates c++11 clang friend


【解决方案1】:

解决方法是将声明和定义分开:

class A {
  int x[3];
public:
  A() { x[0]=1; x[1]=2; x[2]=3; }

  template<unsigned I>
  friend int const&at(A const&a) noexcept;

  template<unsigned I>
  friend int foo(A const&a) noexcept;
};

template<unsigned I>
int const&at(A const&a) noexcept
{
  static_assert(I<3,"array boundary exceeded");
  return a.x[I];
}

template<unsigned I>
int foo(A const&a) noexcept
{
  int tmp = at<I>(a);
  return tmp*tmp;
}

【讨论】:

  • @DrewDormann:因为 Xeo 在 cmets 中针对该问题所写的内容。 (顺便说一句,+1)
  • 这是否意味着clang是正确的而其他编译器是错误的?
  • 顺便说一句,你只需要一个 declaration 出现在命名空间中,定义仍然可以在类命名空间内(尽管它不会有任何区别,除了 for代码的读者)
猜你喜欢
  • 1970-01-01
  • 2016-06-23
  • 2010-12-19
  • 1970-01-01
  • 1970-01-01
  • 2011-07-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多