From: jimc@pic.ucla.edu
Subject: Much trouble with pointer to function
Organization: GNUs Not Usenet
Distribution: gnu
Date: Thu, 7 Jan 1993 04:01:11 GMT

Gnu g++ v2.3.3 for Sparc-SunOS-4.1.1

A template function has an argument which is a pointer-to-function that
takes arguments of the template class.  No amount of wriggling will get
a call to this function to compile.  The complaint is "type unification
failed for function template `xxx'".  Relevant issues are:

1.  Can the compiler recognize that anything (e.g. an explicitly typed
pointer-to-function) matches the template function pointer argument? 
The internal error 180 in this case has been reported separately.

2.  When a template function name is the argument, can the compiler
recursively determine that it's capable of generating an instance which
will match the required argument type?  (And what does the present draft
standard say about which recursions the compiler is required or forbidden
to do?  If the template function args use a typedef defined within the
template arg class, it's "not of aggregate type", e.g.:

	template <class T> struct gorf {
		typedef whatever BASE;
		etc.
	};
	template <class G> testfcn(G g, G::BASE thing) //Rejects G::BASE
	template <class T> testfcn(gorf<T> g, gorf<T>::BASE thing) //Rejected

3.  Probably related: what's being complained about in the warning
"contravariance violation for method types ignored"?

James F. Carter        (213) 825-2897
UCLA-Mathnet;  6221 MSA; 405 Hilgard Ave.; Los Angeles, CA, USA  90024-1555
Internet: jimc@math.ucla.edu            BITNET: jimc%math.ucla.edu@INTERBIT
UUCP:...!{ucsd,ames,ncar,gatech,purdue,rutgers,decvax,uunet}!math.ucla.edu!jimc


-------- Source file

//  bug19.C -- type unification failed for pointer-to-function template

#include <stdlib.h>
#include <iostream.h>

template<class T>
class data {
    int siz;
    T* stuff;
  public:
    data(int n) : siz(n), stuff(new T[n]) { }
    ~data()
	{ delete stuff; }
    int dim() const
	{ return siz; }
    const T& operator [] (int i) const
	{ return stuff[i]; }
    T& operator [] (int i)
	{ return stuff[i]; }
    static int compare(T* a, T* b)		//Nasty surprise if T=double
	{ return (int)(*a - *b); }
    friend ostream& operator << (ostream& f, const data<T>& d);
    void sortme()
	{ qsort(stuff, dim(), sizeof(T), compare); }
//kab.C:26: warning: contravariance violation for method types ignored
// In stdlib.h: void qsort(void*, size_t, size_t, auto int (*ptf)(void*,void*));
};

template <class T> ostream& operator << (ostream& f, const data<T>& d) {
    for (int i = 0; i < d.dim(); ++i)
	f << d[i] << ' ';
    return f;
}
	
template<class T>
int compare(T* a, T* b){ return *a - *b; }

template<class T>
void sort( data<T>d, int (*compare)(T*,T*) )
{ 
     qsort(&(d[0]), d.dim(), sizeof(T), compare); 
}

main(){
	data<int> d(5);
	for (int i = 0; i < d.dim(); ++i)
	    d[i] = d.dim() - i;
	cout << "Before\t" << d << '\n';
//	d.sortme();	// Works

//	sort(d, compare);
//		 type unification failed for function template `sort'

//	int (*cptr)(int*,int*) = compare;	//Gets internal err 180
//	sort (d, cptr);

//	sort(d, d.compare);
//		 type unification failed for function template `sort'

	int (*cptr)(int*,int*) = d.compare;	//Initialization works
	sort (d, cptr);
//		 type unification failed for function template `sort'

	cout << "After\t" << d << '\n';
}

Newsgroups: gnu.g++.bug