哪一个编译器是对的?
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;
}
Run Code Online (Sandbox Code Playgroud)
编译正常: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.
Run Code Online (Sandbox Code Playgroud)
\xc2\xa7 11
\n\n\n\n\n8 默认参数 (8.3.6) 中的名称在声明点绑定,并且在该点而不是在使用默认参数的任何点检查访问权限。函数模板和类模板的成员函数中的默认参数的访问检查按照 14.7.1 中的描述执行。
\n
\xc2\xa7 14.7.1
\n\n\n\n\n12 如果以需要使用默认参数的方式调用函数模板
\nf,则会查找依赖名称,检查语义约束,并按以下方式完成默认参数中使用的任何模板的实例化如果默认参数是在函数模板专业化中使用的初始化程序,\n 具有与f当时使用的函数模板相同的作用域、相同的模板参数和相同的访问权限。这种分析称为默认参数实例化。然后将实例化的默认参数\n 用作 的参数f。
所以,据此,我猜测gcc的解释是正确的。 fun可以访问私有成员,因此应在同一访问中考虑其默认参数。但我在字里行间读到,14.7.1(12) 适用于成员模板,而不仅仅是函数模板。我也可能误解了 14.7.1(12) 的含义。