Bug 53660 - function pointer conversion function template with nested-name-specifier ignored
Summary: function pointer conversion function template with nested-name-specifier ignored
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.7.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-06-13 19:30 UTC by David Krauss
Modified: 2021-08-06 11:38 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description David Krauss 2012-06-13 19:30:09 UTC
template< bool >
struct enable_if { typedef void (*t)(); };

struct c {
    template< bool t = true >
    operator typename enable_if< t >::t () { return []{}; }
};

int main() {
    c()(); // error: no match for call to ‘(c) ()’
}

http://stackoverflow.com/questions/11018810

In C++03 it seems that it was impossible to define a conversion function template that would render its class Callable. Yet there is a function add_template_conv_candidate (cp/call.c) which seems to be used only for this purpose. It was added back in 1997 and it's not clear that it's been tested in a while. Now with default function template arguments the above construct is possible, and it should be called but isn't.

The problem is that the test for function pointer type (etc.) is applied before instantiation in build_op_call_1. The test probably belongs in add_conv_candidate.
Comment 1 Andrew Pinski 2021-08-04 18:36:54 UTC
I don't think this is a bug.

GCC, ICC and clang all reject it the same way.
MSV rejects it with:
<source>(10): error C2783: 'c::operator enable_if<__formal>::t(void)': could not deduce template argument for 't'
Comment 2 David Krauss 2021-08-04 22:28:20 UTC
(In reply to Andrew Pinski from comment #1)
> I don't think this is a bug.

Right, the behavior looks correct.

As for a nested-name-specifier working in this context, it works if it's not dependent. As for the declaration being a function template, it works as long as the conversion-type-id is not dependent.

Oddly, a dependent conversion-type-id *is* allowed when the function is not templated.

Anyway, the standard says to inspect the conversion function declarations and find the ones referring to function (-pointer, -reference) types. That doesn't admit application of template default arguments, as implicit or explicit conversion does.
Comment 3 David Krauss 2021-08-06 11:38:19 UTC
(The standardese mentions "for each … where the conversion-type-id denotes a type" which excludes the case of being a dependent type.)