私は少なくとも2週間問題にぶら下がっていて、理解できないものにブロックされ、SOで実際の問題を実際に指し示していない質問をしています(愚かな私です!)。最後になりましたが、この質問で私の頭痛の本当のポイントを見つけていたらよかったのにと思います。
特定の型にメンバーメソッドがあるかどうかを検出するためのヘルパーとしてテンプレート構造体を使用してきました。このテンプレート構造体は次のようになります。
template
<
typename Type,
typename Return,
typename Parameter,
Return (Type::*)(Parameter)
> struct W {};
の周りの主なアイデアstruct W
は、4番目のパラメーターとしてSFINAEトリックを使用してテストする必要があるメンバー関数へのメンバー関数ポインターを置くことです。前の質問で代替案が提案され、それは私が持っている多くの概念を理解するのに非常に役立ちました行方不明ですが、結局、それは私の本当の問題を解決しません。
私が取り組んでいるコードは、LinuxプラットフォームとWindowsプラットフォームの両方で機能する必要があります。Windowsに使用しているコンパイラは、Linux側のMSVC(Visual Stuido 2010 10.0)とgcc(Devian 4.4.5-8)です。問題は、同じコードがMSVCでコンパイルされないが、gccでコンパイルされることです(私はショックを受けました。通常は反対です。MSVCは標準に厳密ではないためです)。
問題の原因は、MSVCでのコンパイル中に、SFINAEアプローチがメソッドの検出に失敗することset::insert
でした。この失敗を探すために、簡単なテストを作成しました。
#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
関数ポインタを作成している間は期待どおりに機能するため、コンパイルの宣言はp_1
コンパイルされます。ただし、テンプレートパラメータと同じ署名ではありません。これがset::insert
、SFINAEのシンボル置換中に検出が失敗する理由です。エラーテキストcannot convert from 'overloaded-function'
は、何が起こっているのかについての手がかりを私に提供しません(または私の英語の理解が不十分なため、私は何も見つけることができません)。
一見、問題はシンボルの置換だと思っていましたが、MSVCとgccの両方で失敗した場合は理にかなっています。したがって、今のところ、問題がMSVCコンパイラ固有の方法であるかどうか疑問に思っています。
MSVCで失敗する理由と、gccとMSVCを同じように機能させる方法についての手がかりはありますか?
追加の質問:std::map
そして、赤黒木(またはandの下にあるもの)のMSVC実装の下でメソッドの戻り型としてstd::set
ネストされた型を提供しますが、gcc実装に同等のものはありませんか?_Pairib
::insert
map
set
編集:
冷静な答えを読んだ後、私は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
ますが、パブリックスコープにあり、継承されたメソッドでもあるので、名前の置換中にアクセスできないのはなぜですか?