【问题标题】:Can a private static member be used as a default argument to a member function of its class?可以将私有静态成员用作其类的成员函数的默认参数吗?
【发布时间】:2016-10-28 01:45:11
【问题描述】:

哪一个编译器是对的?

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 version 3.4-1ubuntu3 (tags/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.

【问题讨论】:

  • 这可能与优化有关。有问题的行什么都不做,所以 GCC 可能正在优化它。 GCC 并不总是抱怨它优化出来的东西的错误。如果您真的尝试使用该函数指针,我会很好奇发生了什么。
  • @WilliamKappler Nothing changed.
  • 奇怪的是,如果您将funPrivate 设为不是模板,clang 似乎会接受它。
  • @songyuanyao 更诡异! coliru.stacked-crooked.com/a/c27c76981d1a200e 。我什至不会试图说出其中哪一个(如果有的话)行为正确。
  • @WilliamKappler 有问题的代码 sn-p 已简化,但实际使用会产生相同的错误

标签: c++ gcc clang


【解决方案1】:

§ 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) 的意思。

【讨论】:

  • 如果模板函数的 14.7.1(12) 也暗示模板方法,这将是一个明确的答案
【解决方案2】:

我已经在 msvc13 中测试过代码。此代码有效:

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

【讨论】:

    猜你喜欢
    • 2011-05-31
    • 2020-03-22
    • 2015-01-15
    • 2011-08-04
    • 1970-01-01
    • 2013-05-03
    • 1970-01-01
    相关资源
    最近更新 更多