C++ Logo

std-discussion

Advanced search

Re: Templated entity: non-template friend function

From: David Friberg <david.n.friberg_at_[hidden]>
Date: Thu, 5 May 2022 16:07:19 +0200
Defining a function at its friend declaration of a class template means the
definition will only be available once specializations of the class
template are instantiated. If the signature of the function does not rely
on a template parameter of the enclosing class template, the class template
may only be instantiated exactly for one single specialization in each
translation unit (implicitly inline, so different specializations in
different translation units are fine, as long as the definition does not
depend on the template parameter):

template<typename>
struct S {
    friend void f() {}
};

S<int> si{}; // f() definition instantiated
S<char> sc{} // ODR-violation, [basic.def.odr]/1

In your example the friend declaration is different for each specialization
of S, and you do not risk ODR, however at the point where you are asking
for the address of the friend function, it is yet to be defined, as the
class template has not yet been instantiated (for the S<256>
specialization), and GCC correctly emits an undefined reference error.

This behaviour is quite well-known and can be (ab)used to circumvent
private access rules via means of explicit instantiation definitions (and
in C++20: explicit specialitions); see e.g.
https://dfrib.github.io/a-foliage-of-folly/.

BR
David


> Message: 3
> Date: Thu, 05 May 2022 12:27:38 +0300
> From: Vladimir Grigoriev <vlad.moscow_at_[hidden]>
> To: Brian Bi <bbi5291_at_[hidden]>
> Cc: std-discussion_at_[hidden]
> Subject: Re: [std-discussion] Templated entity: non-template friend
> function
> Message-ID: <1651742858.636395871_at_[hidden]>
> Content-Type: text/plain; charset="utf-8"
>
>
> Try this code
>
> https://gcc.godbolt.org/z/Mrb3WzMv7
>
> If to write
>
> inline X< 256 > operator +( const X< 256 >&, const X< 256 >&) noexcept ;
>
> then the error message is
>
> <source>:24: undefined reference to `S::operator+(S::X<256u> const&,
> S::X<256u> const&)'
>
> You can meet me at http://cpp.forum24.ru/ or www.stackoverflow.com or
> http://ru.stackoverflow.com
>

Received on 2022-05-05 14:07:30