Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SFINAE: some failures more equal than others?

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'
like image 819
c-urchin Avatar asked Nov 14 '22 08:11

c-urchin


1 Answers

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.

like image 122
4 revs Avatar answered Dec 21 '22 09:12

4 revs