C++ 私有静态成员是否可以用作其类的成员函数的默认参数?
哪一个编译器是正确的C++ 私有静态成员是否可以用作其类的成员函数的默认参数?,c++,gcc,clang,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>();
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;
}
A类
{
公众:
模板
void fun(void(*f)(=funPrivate){}
私人:
模板
静态void funPrivate(){}
};
int main(int argc,字符**argv)
{
A A;
a、 乐趣();
返回0;
}
编译良好:gcc版本4.8.5(Ubuntu 4.8.5-2ubuntu1~14.04.1)
导致以下错误:clang版本3.4-1ubuntu3(标签/发布\最终版)(基于LLVM 3.4)
a.cpp:5:27:错误:“funPrivate”是“a”的私有成员
void fun(void(*f)(=funPrivate){}
^~~~~~~~~~~~~
a、 cpp:14:3:注意:此处需要实例化“fun”的默认函数参数表达式
a、 乐趣();
^
a、 cpp:8:16:注:此处声明为私有
静态void funPrivate(){}
^
生成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)的意思。我已经在msvc13中测试了代码。此代码适用于:
class A
{
template <typename T>
static void funPrivate() {}
public:
template <typename T>
void fun(void (*f)() = funPrivate<T>) {}
};
A类
{
模板
静态void funPrivate(){}
公众:
模板
void fun(void(*f)(=funPrivate){}
};
这可能与优化有关。该行没有任何功能,因此GCC可能正在对其进行优化。GCC并不总是抱怨它优化出的东西中的错误。如果你真的试图使用那个函数指针,我会很好奇发生了什么。@WilliamKappler奇怪的是,如果你把funPrivate
设为非模板,clang似乎会接受它。@songyuanyao它甚至更奇怪。我甚至不想说哪一个(如果有)是正确的。@WilliamKappler有问题的代码片段被简化了,但实际使用会产生相同的错误如果模板函数的14.7.1(12)也暗示了模板方法,这将是一个明确的答案
class A
{
template <typename T>
static void funPrivate() {}
public:
template <typename T>
void fun(void (*f)() = funPrivate<T>) {}
};