c++/10619: [diagnostic] Error message for no matching function calls does not list explicitally-specified template arguments

giovannibajo@libero.it giovannibajo@libero.it
Sun May 4 14:56:00 GMT 2003


Old Synopsis: Instantiation through function template return type causes too cryptic error.
New Synopsis: [diagnostic] Error message for no matching function calls does not list explicitally-specified template arguments

State-Changed-From-To: open->analyzed
State-Changed-By: bajo
State-Changed-When: Sun May  4 14:44:57 2003
State-Changed-Why:
    Your understanding of what the compiler does are wrong.
    When template functions are found during the
    lookup phase, the compiler _tries_ to specialize them,
    following several rules: it tries to deduce the template
    parameters from the arguments passed and/or uses the 
    explicitally specified template parameters. If the 
    deduction fails and/or is not possible to specialize the
    function in a way that would match the call, the function
    is _not_ instantiated _and_ it is not added to the 
    overload set (which will be used later to decide which 
    function must be called).
    
    De-legalizing the above, in your case, what happens is
    that the compiler detects that it is impossible to 
    specialize f() in a way which would match a call like
    "f<0>()," because specializing with I=0 leads to a type 
    error in the return type. Thus, the template function f() 
    is not added to the overload set. Since there are no more 
    functions called f(), the overload set ends up being
    empty, and the compiler correctly complains that there
    are no matching functions for call to f(). 
    
    This is actually a feature of the language: you can use
    type deduction together with overload as a way to detect
    valid constructs. A quick example is the common is_class
    template trick, which uses deduction and overload to 
    detect a class: the trick is that a class is an entity T 
    for which declaring a pointer such as "void (T::*)(void)" 
    is a valid construct:
    
    --------------------------------------------------------
    template <typename T>
    struct is_class
    {
    	typedef char yes;
    	typedef double no;
    
    	template <typename Q>
    	static yes func(void (Q::*)(void));
    
    	template <typename Q>
    	static no func(...);
    
    	enum { value = sizeof(func<T>(0)) == sizeof(yes) };
    
    	// due to another bug, in GCC currently you need:
    	//  sizeof(is_class::template func<T>(0))
    	// to make the above line compile
    };
    
    struct Foo {}
    
    is_class<int>::value; // 0
    is_class<Foo>::value; // 1
    --------------------------------------------------------
    
    
    * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    
    Anyway, I keep this PR open for another reason. Given the
    following code snippet:
    
    -----------------------------
    template <typename T>
    void foo(int );
    
    int main()
    {
    	foo<0>(4);
    }
    
    -----------------------------
    pr10619.cpp: In function `int main()':
    pr10619.cpp:8: error: no matching function for call to `foo(int)'
    
    
    The error message is slightly wrong. It's not true that there
    are no matching calls "foo(int)". The problem here is that there
    are no matching calls for "foo<0>(int)". The error message does
    not list the explicitally specified template argument, which is
    the real problem for the call to fail. I think that the error
    message should rather be:
    
    "no matching function for call to foo<0>(int)"
    
    Then, I keep this as a change request for diagnostic.

http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=10619



More information about the Gcc-bugs mailing list