我一直在解決至少兩週的問題,被我無法理解的東西阻塞,並且在SO中提出的問題並未真正指向真正的問題(愚蠢的我!)。最後,現在,我希望在這個問題上我發現了我最頭疼的一點。MSVC指向模板參數中重載函數的指針
我一直在使用的模板結構作爲輔助檢測一個給定的類型是否有一個成員方法還是不行,這個模板結構是這樣的:
template
<
typename Type,
typename Return,
typename Parameter,
Return (Type::*)(Parameter)
> struct W {};
角落找尋struct W
的主要思想是把作爲第四個參數的成員函數指針指向我需要使用SFINAE技巧測試的成員函數in a previous question提出了一個替代方案,它幫助我理解了許多我一直想念的概念,但最終它並不能解決我真正的問題。
我正在使用的那段代碼必須在Linux和Windows平臺上工作,我用於windows的編譯器是MSVC(Visual Stuido 2010 10.0)和gcc(Devian 4.4.5-8)在Linux方面。問題是,同一段代碼不能在MSVC中編譯,但它在gcc中(我很震驚,通常是相反的,因爲MSVC不太標準)。
問題的起源是我的SFINAE方法無法檢測方法set::insert
而MSVC下編譯,爲了尋找這個失敗,我寫了一個simple test:
#include <set>
int main(int argc, char **argv)
{
typedef std::set<int> setint;
std::pair<setint::iterator, bool> (setint::*p_1)(const setint::value_type &) = &setint::insert;
W<setint, std::pair<setint::iterator, bool>, const setint::value_type &, &setint::insert> w_1;
return 0;
}
就像我之前提到:這使用gcc編譯樣本沒有問題,但在使用MSVC在w_1
聲明給出了一個錯誤:
error C2440: 'specialization' : cannot convert from 'overloaded-function' to 'std::pair<_Ty1,_Ty2> (__thiscall std::set<_Kty>::*)(const int &)'
with
[
_Ty1=std::_Tree_const_iterator<std::_Tree_val<std::_Tset_traits<int,std::less<int>,std::allocator<int>,false>>>,
_Ty2=bool,
_Kty=int
]
None of the functions with this name in scope match the target type
在創建函數指針正常工作,所以聲明編譯;但與模板參數相同的簽名沒有。這就是在SFINAE的符號替換過程中set::insert
檢測失敗的原因。錯誤文本cannot convert from 'overloaded-function'
沒有提供任何有關正在發生的事情的線索(或者我無法找到任何,因爲我的英語不好)。乍一看,我一直認爲問題是符號替換,但如果MSVC和gcc都失敗了,它也會有意義。所以現在我想知道問題是否是某種MSVC編譯器特定的方式來做事情。
任何線索爲什麼它在MSVC下失敗,以及如何使gcc和MSVC以同樣的方式工作?
額外的問題:std::map
和std::set
提供了嵌套式_Pairib
作爲返回類型::insert
方法MSVC實現紅黑樹(或一切map
和set
下)下,有一個在GCC實現不相同呢?
編輯:
閱讀chill answer之後,我進去看了MSVC的std::set
實現。
std::set
是派生類的std::_Tree
提供我想要查詢的方法,包括:
// class std::_Tree, file xtree in the path 'VisualStudioPath/VC/include/'
_Pairib insert(const value_type& _Val)
{ // try to insert node with value _Val, favoring right side
return (insert(_Val, false));
}
該插入方法屬於std::_Tree
範圍,而不是std::set
範圍,但它是到公共範圍和是一個繼承的方法,所以爲什麼它在名稱替換期間不可訪問?
關於額外的問題:'_Pairib'保留用於執行的名稱,用戶代碼不應該參考它。保留標識符的集合是:標識包含雙下劃線('__'),或以任何名稱空間中的單個下劃線和大寫字母('_P..')開頭,或單個下劃線後面跟全局名稱空間中的任何字符。 –