The following program should compile, but current g++ from trunk compiles it.
Please read the comments in the code:
typedef T type;
template<typename T> struct is_function;
// Let's name this template partial specialization #1
struct is_function< T ()>
template<typename T> struct is_member_func;
template<typename T, typename C>
struct is_member_func<T C::*>
// okay, the following line should not compile. Here is why.
//After the type substitution that happens at instantiation time,
//the value of the argument that matches the T parameter is
//'void () () const'.
//In that context, the result of the substitution of T in the expression
//do_typedef<T>::type _should_ be 'void () () const' as well.
//So will be the argument of the is_function template.
//'void () () const' is not compatible with 'T ()', so the
//partial template specialization #1 should be instantiated.
//So we should get a compilation error.
is_function<typename do_typedef<T>::type> t;
// Should not compile because of the comment  above.
is_member_func<void (A::*) (void) const> t;
What happens is that during the type substitution of
do_typedef<T>::type, g++ removes the const qualifier from the 'void () () const' function. And that is a bug.
I'll attach below a patch that fixes it.
Created attachment 17372 [details]
Don't remove cv quals from typedefs during type substitution
This is related to bug 37806.
*** This bug has been marked as a duplicate of 37806 ***