I came across some code written in VS7.1 and now I'm trying to get it to work on MacOSX. The code snippet below, which I understand about SFINAE . From what I understand, the code is used at compile time, you know what type it is, relying on some magic to instantiate. In short, the correct overload is chosen by considering the template argument.
Here is the code I have. It is somewhat simplified to show only the problem.
template <typename T> struct SomeClass { }; template <> struct SomeClass<char> { typedef char Type; }; template <typename T> struct IsChar { typedef char Yes; typedef int No; template <typename U> static Yes Select(U*, typename SomeClass<U>::Type* p = 0); template <typename U> static No Select(U*, ...); static T* MakeT(); const static bool Value = sizeof(Select(MakeT())) == sizeof(Yes); };
I just use it like this:
if (IsChar<int>::Value) { ...
When compiling , the above code works well , and it selects the top-most class due to the lack of a typedef for Type when using int.
If now I use char ...
if (IsChar<char>::Value) { ...
... the compiler will complain about ambiguous selection functions because it does not know which one to use. From what I read, overload resolution gives the least preference to the ellipsis parameter (...). Therefore, he must know to choose the first.
The code worked fine, at least on VS7.1, but not on gcc for MacOSX, and not on gcc4.4 for Linux.
Any suggestions for fixing this? Maybe this is usually done differently?
Thanks!
UPDATE: I realized that the sample code I gave may be a little too simplified, because I believe that we do not check the type here, even if I mistakenly do so. I need to collect a little more information for you today, since I do not have the code here. Sorry for that.
UPDATE2: Even if my tradition is bad and this is because you are not familiar with the source code or using templates in this way. Meanwhile, I dig out a little more information, let it be assumed that these constructions are for some reason X and the names that I gave are all wrong, but what about the compiler problem? Why can't he choose the right overloaded function here? This is interesting to me too. As I said, I will return with a better explanation of what the common goal is.
Edit
After a closer look at the source code, boost :: integral_constant and boost :: enable_if are used, as suggested here. The problem is something specific, how the template arguments are output, and it does not work the way it was configured. However, following what George suggested at the end of my answer, I could fix things in order to accept things. I have the following:
typedef char Yes; typedef int No; template <typename U> static Yes Select(typename SomeClass<U>::Type* p); template <typename U> static No Select(...); static const bool Value = sizeof(Select<T>(0)) == sizeof(Yes);
It works well. During the experiments, I found that the presence of two functional parameters in the Select functions leads to a problem. I did not find a reason. I will come back to this when I better understand.
Thank you for your help. At least now I understand the principles here and how everything should work. Only some details that are still unknown.