您好CRTP相关的编译器错误,上的指针到一个成员函数默认值
同时使基于CRTP,通用包装调用任意库函数,我遇到一个问题,我理解有困难。下面是一个非常简化的代码来说明问题:
#include <iostream>
template< typename PValue, typename PDerived >
class TBase
{
private:
typedef TBase TSelf_;
typedef PDerived TDerived_;
protected:
typedef PValue TValue_;
protected:
TBase(void)
{
std::cout << " TBase::TBase() " << std::endl;
}
public:
void Foo(void)
{
std::cout << " TBase::Foo() " << std::endl;
}
template< typename PType >
static void Call(PType /*pSomething*/, void(TDerived_::*pFunction)(void) = &TSelf_::Foo, TDerived_ pDerived = TDerived_())
{
(pDerived.*pFunction)();
std::cout << " static TBase::Call(). " << std::endl;
}
};
template< typename PValue >
class TDerived : public TBase< PValue, TDerived<PValue> >
{
friend class TBase< PValue, TDerived<PValue> > ;
private:
typedef TBase< PValue, TDerived > TBase_;
typedef TDerived TSelf_;
public:
TDerived(void) :
TBase_()
{
std::cout << " TDerived::TDerived() " << std::endl;
}
void Foo(void)
{
std::cout << " TDerived::Foo() " << std::endl;
}
void Bar(void)
{
std::cout << " TDerived::Bar() " << std::endl;
}
};
int main(void)
{
TDerived<int>::Call(1);
TDerived<int>::Call(1, &TDerived<int>::Foo);
TDerived<int>::Call(1, &TDerived<int>::Bar, TDerived<int>());
return (0);
}
一切都按照预期编译和工作。不过,如果我尝试在TBase::Call(...)
使用指针TDerived::Foo()
作为第二个参数的默认参数:
static void Call(PType /*pSomething*/, void(TDerived_::*pFunction)(void) = &TDerived_::Foo, TDerived_ pDerived = TDerived_())
编译器提供了一个语法错误......我有一种感觉它关系到编译器如何解析代码和它无法找出指向尚未定义(或实例化)类的函数的指针。但是,调用TDerived
构造函数作为TBase::Call(...)
的第三个参数的默认参数没有任何问题。有人能给我一个关于发生了什么的明确答案吗?为什么派生类MFP不被接受,并且派生类的对象被接受为默认参数?
谢谢。
编辑:编译器的错误(MSVS2010命令行编译):
FMain.cpp(224) : error C2061: syntax error : identifier 'TDerived_'; FMain.cpp(233) : see reference to class template instantiation 'TBase<PValue,PDerived> with [PValue=int,PDerived=TDerived<int>]' being compiled; FMain.cpp(323) : see reference to class template instantiation 'TDerived<PValue> with [PValue=int]' being compiled
这是一个语法错误 - 它不承认TDerived_
如在MFP的默认参数类型。在这之后还有其他错误,它们都是语法错误,因为函数定义现在是不合格的。这就是我的理解。
编辑:基本上,我不明白为什么我可以使用TDerived_
作为默认参数的对象,但不能使用指向成员函数的指针作为默认参数。
编辑:好吧,这现在让我疯了。 首先,我改为typedef TBase< PValue, TDerived > TBase_;
,因为它被指出(谢谢,伙计们!)。实际上,它只在MSVC++下编译,因为此编译器不执行两部分解析;即在codepad.org上(它使用g ++ 4.1.2),它没有编译。 其次,在那之后,我尝试在codepad.org上使用static void Call(PType /*pSomething*/, void(TDerived_::*pFunction)(void) = &TDerived_::Foo, TDerived_ pDerived = TDerived_())
,并且......编译并正确运行!所以我现在真的很困惑:人们向我解释为什么它不正确(我不明白“为什么”(参见我之前的编辑)),现在事实证明g ++编译它是正确的......这是否意味着它只是MSVC++的问题,而不是代码?或者,从标准的角度来看,代码确实存在问题(我看不到它),并且g ++“错误地”接受它(不太可能,我想)?帮助?!
编译器给出了什么错误?你为什么不发布这个呢?是否希望我们编译此代码并自己查看错误? – Nawaz
“语法错误”错误消息是可能的最不有用的诊断消息(除“某处出现错误”)。 – curiousguy
回复:您最近的评论 - 在typedef更改后,代码对我来说很合适,但也许对标准有更广泛认识的人可以发表评论。 FWIW,在VS2008和GCC 4.2.1上编译并运行后, – msandiford