私有静态成员可以用作其类成员函数的默认参数吗?

时间:2016-06-03 15:02:41

标签: c++ gcc clang

哪一个编译器是对的?

class A
{
public:
   template <typename T>
   void fun(void (*f)() = funPrivate<T>) {}
private:
   template <typename T>
   static void funPrivate() {}
};

int main(int argc, char** argv)
{
  A a;
  a.fun<int>();
  return 0;
} 

编译好: gcc版本4.8.5(Ubuntu 4.8.5-2ubuntu1~14.04.1)

导致错误: clang版本3.4-1ubuntu3(标签/ RELEASE_34 / final)(基于LLVM 3.4)

    a.cpp:5:27: error: 'funPrivate' is a private member of 'A'
   void fun(void (*f)() = funPrivate<T>) {}
                          ^~~~~~~~~~~~~
    a.cpp:14:3: note: in instantiation of default function argument expression for 'fun<int>' required here
      a.fun<int>();
      ^
    a.cpp:8:16: note: declared private here
       static void funPrivate() {}
               ^
1 error generated.

2 个答案:

答案 0 :(得分:2)

§11

  

8默认参数(8.3.6)中的名称在声明点绑定,并在此处检查访问   指向而不是默认参数的任何使用点。访问检查中的默认参数   功能模板和类模板的成员函数按照14.7.1。

中的描述执行

§14.7.1

  

12如果以需要使用默认参数的方式调用函数模板f,则依赖名称     查找,检查语义约束,以及默认情况下使用的任何模板的实例化    参数完成就像默认参数是函数模板特化中使用的初始化器一样   具有相同的范围,相同的模板参数和与功能模板f相同的访问权限   在那时使用。此分析称为默认参数实例化。实例化的默认参数   然后用作f的参数。

所以,根据这个,我猜想gcc的解释是对的。 fun可以访问私有成员,因此应该在同一访问中考虑其默认参数。但我正在阅读14.7.1(12)适用于成员模板的行,而不仅仅是函数模板。我也可能误解了14.7.1(12)的意思。

答案 1 :(得分:0)

我在msvc13中测试了代码。此代码有效:

class A
{
  template <typename T>
  static void funPrivate() {}
public:
  template <typename T>
  void fun(void (*f)() = funPrivate<T>) {}
};