您好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