[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