在requires子句中访问私有成员

考虑以下程序:

#include <iostream>

template<typename T> void f1(T& v)
{
  std::cout << "f1: can call g" << std::endl;
  v.g();
}

template<typename T> void f2(T& v) requires requires (T& v) { v.g(); }
{
  std::cout << "f2: can call g" << std::endl;
  v.g();
}

template<typename T> void f2(T&) requires (!requires (T& v) { v.g(); })
{
  std::cout << "f2: cannot call g" << std::endl;
}

class A
{

public: // if commented out, f2 will not call g anymore

  void g()
  {
    std::cout << "g called" << std::endl;
  }

  template<typename T> friend void f1(T& v);
  template<typename T> friend void f2(T& v);
};

class B
{
};


int main()
{
  std::cout << "A" << std::endl;
  A a{};
  f1(a);
  f2(a);

  std::cout << "B" << std::endl;
  B b{};
  f2(b);

  return 0;
}

该函数g可能存在于类中,也可能不存在。如果是(如 for A),函数f2应该调用它,如果不是(如 for B)它不应该调用。这种区别是通过requires子句进行的。

我结识了f2A所以g即使是私密的,它也应该能够打电话(一般来说,结交工作很好,请参阅 参考资料f1)。然而,requires似乎忽略了该函数是友好的,因此,当g在 中设为私有时Ag不再被调用。

为什么是这样?是否有解决方法,即调节是否可以调用函数,即使它是私有的(但已成为朋友)?也许甚至使用旧学校std::enable_if

回答

当您为函数或函数模板添加好友时,只有该函数的主体可以访问,而不是它的各种装备。附加到它的约束是无关紧要的。

您可以通过在 的主体内移动检查来解决此问题f2,以便在具有此访问权限的上下文中检查它:

template <typename T>
void f2(T& v)
{
    if constexpr (requires { v.g(); }) {
        std::cout << "f2: can call gn";
        v.g();
    } else {
        std::cout << "f2: cannot call gn";
    }
}


以上是在requires子句中访问私有成员的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>