I have just begun dabbling with SFINAE and I am having trouble understanding the syntax behind the most often-used example which appears in various forms, but the idea is to check whether a particular type contains a given member. This particular one is from Wikipedia:
template <typename T> struct has_typedef_foobar
{
typedef char yes[1];
typedef char no[2];
template <typename C> static yes& test(typename C::foobar*);
template <typename> static no& test(...);
static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};
There are a couple of things I don't get about this:
- What is the argument type of the test() overload that returns "yes"? Is it a pointer? Why the typename keyword used as part of the argument? I've seen it used also for testing if a class has a member of a given type, not just a typedef, and the syntax remains unchanged.
- Sometimes I've seen examples that use test(int C::*). This is even more strange, no idea what member of C are we referencing. If it was a real function with a body, instantiated for a real type, and the argument was named, what would it point to and how would you use it?
template <typename T> func(int T::*arg) { *arg = 1; } struct Foo { int x; } foo; func<Foo>(&foo::x); // something like this? func(&foo::x); // or maybe even like this?
- Is template <typename> with no symbol allowed if it's not being used in the second overload? How is it even a template function then?
- Bonus: Could it be made to check for existence of more than one member at a time?