C++ 指向成员函数默认值的指针出现CRTP相关编译器错误
你好 在制作一个基于CRTP的通用包装器来调用任意库函数时,我遇到了一个难以理解的问题。下面是一个非常简单的代码来说明这个问题:C++ 指向成员函数默认值的指针出现CRTP相关编译器错误,c++,templates,crtp,pointer-to-member,C++,Templates,Crtp,Pointer To Member,你好 在制作一个基于CRTP的通用包装器来调用任意库函数时,我遇到了一个难以理解的问题。下面是一个非常简单的代码来说明这个问题: #包括 模板 类数据库 { 私人: typedef TBase TSelf; typedef PDerived t派生; 受保护的: typedef PValue TValue_2;; 受保护的: t基地(无效) { std::cout; 私人: typedef TBaseTBase; typedef t导出的TSelf; 公众: t导出(无效): t基地() { s
#包括
模板
类数据库
{
私人:
typedef TBase TSelf;
typedef PDerived t派生;
受保护的:
typedef PValue TValue_2;;
受保护的:
t基地(无效)
{
std::cout;
私人:
typedef TBaseTBase;
typedef t导出的TSelf;
公众:
t导出(无效):
t基地()
{
std::cout());
返回(0);
}
一切都按照预期进行编译和工作。但是,如果我尝试使用指向TDerived::Foo()
的指针作为TBase::Call(…)
中第二个参数的默认参数:
静态void调用(PType/*pSomething*/,void(TDerived_u::*pFunction)(void)=&TDerived_uU::Foo,TDerived_UpDerived=TDerived_Uf())
编译器给出了一个语法错误…我感觉它与编译器如何解析代码有关,它无法找出指向尚未定义(或实例化)类的函数的指针。但是,它可以调用TDerived
构造函数作为TBase::Call(…)的第三个参数的默认参数
。有人能给我一个明确的答案吗?为什么不接受派生类MFP,而接受派生类的对象作为默认参数
谢谢
编辑:编译器错误(MSVS2010命令行编译器):
FMain.cpp(224):错误C2061:语法错误:标识符'TDerived_uu';FMain.cpp(233):请参阅正在编译的类模板实例化'TBase with[PValue=int,PDerived=TDerived];FMain.cpp(323):请参阅正在编译的类模板实例化'TDerived with[PValue=int]'
这是一个语法错误-它无法识别MFP的默认参数中的类型为t派生\
。这之后还有其他错误,它们都是语法错误,因为函数定义现在格式不正确。这就是我对它的理解
编辑:基本上,我不明白为什么我可以使用t派生的对象作为默认参数,但不能使用指向成员函数的指针作为默认参数
编辑:好吧,这让我快发疯了。
首先,我改为typedef TBaseTBase;
,正如前面所指出的(谢谢大家!)。事实上,它只在MSVC++下编译,因为这个编译器不进行两部分解析;例如,在codepad.org上(使用g++4.1.2),它没有编译。
其次,在那之后,我尝试在codepad.org上使用静态void调用(PType/*pSomething*/,void(TDerived\uuU:*pFunction)(void)=&TDerived\uUfoo,TDerived\uUpDerived=TDerived\uUfoo())
,它编译并正确运行了!所以我现在真的很困惑:人们向我解释了为什么它不正确(我不明白“为什么”(见我之前的编辑)现在发现g++编译正确了…这是否意味着这只是MSVC++的问题而不是代码?或者代码确实有问题,从标准的角度来看(我看不到),g++“错误地”接受了它(我想不太可能)?…帮助?!导出的t中的t值
参数对t基础
的typedef中类型的作用域似乎是错误的(!)
你有:
private:
typedef TBase< TValue_, TDerived > TBase_;
private:
typedef TBaseTBase;
我认为你需要:
private:
typedef TBase< typename TBase< PValue, TDerived< PValue > >::TValue_, TDerived > TBase_;
private:
typedef TBase>::TValue,TDerived>TBase;
甚至只是:
private:
typedef TBase< PValue, TDerived > TBase_;
private:
typedef TBaseTBase;
< > >强>编辑< /强>:C++标准部分(3):
在类或类模板的定义中,如果是基类
根据模板参数,不检查基类范围
在非限定名称查找期间,在
类模板或成员,或在类的实例化过程中
模板或成员
t导出的中的t值
参数对t基础
的typedef中的类型的作用域似乎是错误的(!)
你有:
private:
typedef TBase< TValue_, TDerived > TBase_;
private:
typedef TBaseTBase;
我认为你需要:
private:
typedef TBase< typename TBase< PValue, TDerived< PValue > >::TValue_, TDerived > TBase_;
private:
typedef TBase>::TValue,TDerived>TBase;
甚至只是:
private:
typedef TBase< PValue, TDerived > TBase_;
private:
typedef TBaseTBase;
< > >强>编辑< /强>:C++标准部分(3):
在类或类模板的定义中,如果是基类
根据模板参数,不检查基类范围
在非限定名称查找期间,在
类模板或成员,或在类的实例化过程中
模板或成员
简单:实例化TBase
模板类定义时,调用
函数模板的声明被实例化:
template< typename PType >
static void Call( PType , void(TDerived_::*pFunction)() = &TSelf_::Foo, TDerived_ pDerived = TDerived_() )
在TBase
模板类定义实例化期间未声明TDerived\uuuuo::Foo()
顺便说一句,您不需要将参数列表指定为(void)
;()
具有相同的效果,并且不太冗长。简单:当实例化TBase
模板类定义时,调用
函数模板的声明被实例化:
template< typename PType >
static void Call( PType , void(TDerived_::*pFunction)() = &TSelf_::Foo, TDerived_ pDerived = TDerived_() )
在TBase
模板类定义实例化期间未声明TDerived\uuuuo::Foo()
顺便说一句,您不需要将参数列表指定为(void)
;()
具有相同的效果,并且是l