I'm trying to use SFINAE to distinguish a class that has a member called 'name'. I set things up in what seems to be the standard pattern but it's not working -- instead of silently ignoring the 'failed' substitution, the compiler produces an error.
I'm sure I've run up against some template substitution rule, I'd be grateful if someone could explain which one.
This is a stripped down example. I'm using gcc:
template <typename U> string test( char(*)[sizeof(U::name)] = 0 ) { return "has name!"; }
template <typename U> string test(...) { return "no name"; }
struct HasName { string name; }
struct NoName {}
cout << "HasName: " << test<HasName>(0) << endl; //fine
cout << "NoName: " << test<NoName>(0) << endl; //compiler errors:
//error: size of array has non-integral type `<type error>'
//error: `name' is not a member of `NoName'
The following appears valid (although as Michael says, it doesn't necessarily give the result you want on other compilers):
#include <string>
#include <iostream>
using namespace std;
template <typename U> string test( char(*)[sizeof(U::name)] = 0 ) { return "has name!"; }
template <typename U> string test(...) { return "no name"; }
struct HasName { static string name; };
struct NoName { };
int main() {
cout << "HasName: " << test<HasName>(0) << endl;
cout << "NoName: " << test<NoName>(0) << endl;
}
Output:
HasName: has name!
NoName: no name
gcc (GCC) 4.3.4 20090804 (release) 1
Comeau also accepts the code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With