I've been hanging around a problem for at least two weeks, being blocked by stuff that I'm not able to understand and making questions in SO that doesn't really pointed to the real problem (silly me!). Finally now, I wish I had found the real point of my headache in this question.
I've been using a template struct as helper to detect whether or not a given type has a member method or not, this template struct looks like this:
template
<
typename Type,
typename Return,
typename Parameter,
Return (Type::*)(Parameter)
> struct W {};
The main idea arround the struct W
is to put as fourth parameter a member function pointer to the member function I need to test using the SFINAE trick, in a previous question an alternative was suggested and it helped me so much to understand many concepts that I've been missing, but in the end, it doesn't solves my real problem.
The piece of code that i'm working on, must work in both Linux and Windows platforms, the compiler i'm using for windows is MSVC (Visual Stuido 2010 10.0) and gcc (Devian 4.4.5-8) on Linux side. The problem is that the same piece of code doesn't compile in MSVC but it does in gcc (I was shocked, usually is the oposite, cause MSVC is less standard-strict).
The origin of the problem was that my SFINAE approach fails to detect the method set::insert
while compiling under MSVC, in order to look for this fail i wrote a 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;
}
As i mentioned before: this sample compiles without problem using gcc, but while using MSVC gives an error at the declaration of 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
While creating a function pointer works as expected, so the declaration of p_1
compiles; but with the same signature as template parameter does not. This is why the set::insert
detection fails during the symbols substitution of SFINAE. The error text cannot convert from 'overloaded-function'
doesn't provides me any clue about what's going on (or i'm not able to find any, due my poor english understanding).
At first sight, i've been thinking that the problem is the symbols substitution, but it would make sense if it failed in both MSVC and gcc as well. So for now i'm wondering if the problem is some MSVC compiler-specific way to do things.
Any clue about why is it failing under MSVC and how to make gcc and MSVC works in the same way?
Extra question: std::map
and std::set
provides a nested type _Pairib
as return type for ::insert
method under the MSVC implementation of red-black tree (or whatever is under map
and set
), there's no equivalent in the gcc implementation?
EDIT:
After reading the chill answer, I've looked into the MSVC's std::set
implementation.
std::set
is a derived class of std::_Tree
that provides the method i want to check:
// 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));
}
This insert method belongs to the std::_Tree
scope, not to std::set
scope, but it is into the public scope and is a inherited method as well, so why it isn't accesible during the name substitution?