[cfe-dev] Specializing friend template functions?
Mario Lang
mlang at delysid.org
Sat Dec 6 05:35:38 PST 2014
Richard Smith <richard at metafoo.co.uk> writes:
> On Fri, Dec 5, 2014 at 3:55 AM, Mario Lang <mlang at delysid.org> wrote:
>
>> Hi.
>>
>> I sort of have a suspicion that this might be a known issue, but I
>> haven't found anything so far. The code below compiles just fine with
>> GCC, but Clang complains:
>>
>> ---<snip>---
>> class c { template<class> friend bool f(c) { return false; } };
>> template<> bool f<int>(c) { return true; }
>>
>> int main(){}
>> ---<snip>---
>>
>> cl.cc:2:1: error: extraneous 'template<>' in declaration of variable 'f'
>> template<> bool f<int>(c) { return true; }
>> ^~~~~~~~~~
>> cl.cc:2:17: error: redefinition of 'f' as different kind of symbol
>> template<> bool f<int>(c) { return true; }
>> ^
>> cl.cc:1:39: note: previous definition is here
>> class c { template<class> friend bool f(c) { return false; } };
>> ^
>>
>> As I am not an expert on the standard at all, the first question that
>> comes to mind is: is this actually legal? Given how inline friend
>> functions usually work, I have a feeling it should be legal.
>>
>
> I don't think this is legal. For an explicit specialization to be valid,
> name lookup must find the template being explicitly specialized. Name
> lookup for 'f' after the definition of 'c' does not find anything, so the
> declaration appears to be ill-formed. (See [temp.names]p2 and p3.)
I wonder why name-lookup doesn't find anything. At least non-templated
free friend functions have always worked that way. Or is this a GCC
extension I am not aware of?
class d {
...
friend bool operator==(d, d) { ... }
};
// here, d{} == d{} is found
[...]
>> So the FunctionTemplateDecl looks fine, but AST print is a bit messy:
>>
>> class c {
>> friend template <class > bool f(c) {
>> return false;
>> }
>>
>> ;
>> };
>> int main() {
>> }
>>
>> Note, the extra semicolon (likely harmless) and the swapped 'friend'
>> keyword position. I don't know if 'friend' can be switched around like
>> this, but GCC *and* clang actually fail to compile that.
>>
>> I guess the AST printer doesn't really require to always produce valid
>> source code (or does it), but this AST print seems to hint at some gaps
>> in AST handling around FriendDecl and nested TemplateFunctionDecl.
>
> We don't guarantee that the AST printer always produces valid code.
Guessed that.
> The AST dump looks fine to me for this case, though.
Note friend template<class> vs template<class> friend.
The original code was:
>> class c { template<class> friend bool f(c) { return false; } };
and ast-print switched that around to:
>> friend template <class > bool f(c) {
which fails to compile on gcc and clang.
--
CYa,
⡍⠁⠗⠊⠕
More information about the cfe-dev
mailing list