The code bellow compiles without a warning on GCC and issues an error with clang (any c++11 compatible versions of both clang and GCC). Which compiler is right with respect to the standard? Specifically, is it allowed to declare as friend a non partially specialized template alias which is a partial template specialization of a class?
This makes me think that it might not be allowed:
- cppreference says: "Friend declarations cannot refer to partial specializations [...]".
- And also: "A type alias declaration introduces a name which can be used as a synonym for the type denoted by type-id. It does not introduce a new type [...]".
- Finally: "Both function template and class template declarations may appear with the friend specifier [...]". It implicitly excludes the possibility for a template alias to be a friend of a class as an actual template alias but rather as the aliased class template, which is a partial specialization in the snippet bellow.
However, this makes me think that it might be allowed:
- cppreference says : "An alias template is a template [...]". I undestand that a template alias is a distinct template. By consequence, declaring it as friend as in the following example without partial specilization of the class template alias is valid... Or not.
- This code (not from me) also gives a workaround and let me think that there is no obvious reason for making the following code ill-formed.
This post asks a very similar question but no clear answer was provided with respect to the specific usage of an intermediate template alias.
template<typename T,typename N> class B{};
template<typename T> class A{
// template<typename U> friend class B<T,U>; fails as expected
template<typename N> using alias = B<T,N>;
template<typename N> friend class alias;
};
Intent: legal way to declare a partial specialization as friend using an intermediate alias (workaround).
Result: GCC is happy with it and produces the intended behaviour. Clang produces the following error:
<source>:7:35: error: redefinition of 'alias' as different kind of symbol
template<typename N> friend class alias;
^
<source>:6:22: note: previous definition is here
template<typename N> using alias = B<T,N>;