Question about "substitution failure is not an error" concept, SFINAE

A

Aries Sun

The following code can be compiled without error:

typedef char True; // sizeof(True) == 1
typedef struct { char a[2]; } False; // sizeof(False) > 1
//...
template <typename T> True isPtr( T * );
template <typename T> False isPtr(T);

#define is_ptr( e ) (sizeof(isPtr(e))==sizeof(True))

int main() {
int *a;
cout << is_ptr(a) << endl;
}

why the following can compile:
int test();
int main() {
cout << sizeof(test);
}
 
A

Aries Sun

The following code can be compiled without error:

typedef char True; // sizeof(True) == 1
typedef struct { char a[2]; } False; // sizeof(False) > 1
//...
template <typename T> True isPtr( T * );
template <typename T> False isPtr(T);

#define is_ptr( e ) (sizeof(isPtr(e))==sizeof(True))

int main() {
int *a;
cout << is_ptr(a) << endl;

}

why the following can compile:
int test();
int main() {
cout << sizeof(test);

}

I got, because is call sizeof(isPtr(e)), there is a "(" and ")"
 
J

Joel Yliluoma

The following code can be compiled without error:

typedef char True; // sizeof(True) == 1
typedef struct { char a[2]; } False; // sizeof(False) > 1
//...
template <typename T> True isPtr( T * );
template <typename T> False isPtr(T);

#define is_ptr( e ) (sizeof(isPtr(e))==sizeof(True))

Note that normally you would do that like this:

#include <iostream>

struct true_type { enum { result = true }; };
struct false_type { enum { result = false }; };

template<typename T>
struct is_pointer: public false_type
{
};

template<typename T>
struct is_pointer<T*>: public true_type
{
};

int main()
{
std::cout << "char* : " << is_pointer<char*>::result << std::endl;
std::cout << "int : " << is_pointer<int>::result << std::endl;
}

Because true_type and false_type do not have a common anchestor, you
can now also do something like this:

template<typename T>
void handle_something_do(const T& t, false_type); // for non-pointer cases
template<typename T>
void handle_something_do(const T& t, true_type); // for pointer cases

void handle_something(const T& t)
{
handle_something_do(t, is_pointer<T>() );
}

Especially doing a sizeof on a function's return value is somewhat
weird in my opinion. Does the function get called or not? If it
does, what does the function do? How should you implement it? Why
should it take room in the executable, when all that is done is
done at compile time?
 
T

tragomaskhalos

Especially doing a sizeof on a function's return value is somewhat
weird in my opinion. Does the function get called or not?
It doesn't get called - Alexandrescu uses this trick in one of his
books, and it seems fairly common in TMP.
Your way is more elegant though.
 
J

Joel Yliluoma

It doesn't get called - Alexandrescu uses this trick in one of his
books, and it seems fairly common in TMP.
Your way is more elegant though.

Thanks. My questions (which you only quoted one of) in the context
which I posted them were rhetorical by nature, though. They were
questions which may be posed when reading such code.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top