我注意到了一些我认为非常有趣的行为。

考虑下面的示例代码,我试图使其尽可能通用:

class Base
{
public:
  virtual void func() {}
};

class Subclass : public Base
{
public:
  void func() {}
};

class ApplyingClass
{
public:
  static void callFunc(Base& base) { base.func(); }
private:
  template <class T>
  static void callFunc(T& t) { t.func(); }
};

int main()
{
  Subclass s;
  Base& b = s;

  // Error: ApplyingClass::callFunc(T& t) with T=Subclass is private.
  ApplyingClass::callFunc(s);

  // works
  ApplyingClass::callFunc(b);

  return 0;
}

似乎在main()内部,由于存在模板方法,编译器认为模板“ApplyingClass::callFunc(T&t)”最适合函数调用“ApplyingClass::callFunc(s)”并抛出一个错误,因为该方法无法从其类的外部访问。

这似乎合乎逻辑,但我希望编译器仍然尝试使用“ApplyingClass::callFunc(Base&base)”,因为方法签名适合,并且这是唯一可访问的适合方法。

进一步说明我的观点;如果我要从ApplyingClass中删除私有(private)模板方法,则main()中的两个函数调用都将是有效的。

现在我的问题是这是否是C++规范的一部分,或者这是否是编译器特定的行为(已使用Visual Studio 2017 ver 15.5.7编译器进行了测试)。

最佳答案

在这里发出错误的C++是有效的。

参见[class.member.lookup]:



因此,首先选择适当的重载(模板),然后进行访问控制,这将导致编译器错误。

08-16 00:04