Created on 2024-04-30.00:00:00 last changed 1 month ago
CWG 2024-08-16
The proposed resolution above disallows a few examples from paper P2893R3 (Variadic friends), such as
template<class... Ts>
struct VS {
template<class U>
friend class C<Ts>::Nested...; // now ill-formed
};
The adopted wording for P2893R3 makes the friend-type-specifier (not the entire template-declaration) the pattern that is expanded by the pack expansion, leading to the expansion
struct VS<T1, T2, T3> { template<class U> friend class C<T1>::Nested, class C<T2>::Nested, class C<T3>::Nested; };
However, that violates the principle that a template-declaration declares exactly one entity (see issue 2862).
As an aside, the paper as adopted misrepresents the status of members of dependent types, which are covered by 13.7.5 [temp.friend] paragraph 5.
CWG welcomes a paper making the template friend cases valid, but such a facility would appear to require substantial changes to the normative wording, which a core issue is not equipped for.
CWG asks EWG to consent to the reduction in scope for the variadic friends facility, via paper issue cplusplus/papers#2032.
Proposed resolution (2024-08-16):
(This is not a DR.)
(Issue 2862 modifies the same paragraph.)
Change in 13.1 [temp.pre] paragraph 5 as follows:
In a template-declaration, explicit specialization, or explicit instantiation, the init-declarator-list in the declaration shall contain at most one declarator. When such a declaration is used to declare a class template, no declarator is permitted. In a template-declaration whose declaration is a friend-type-declaration, the friend-type-specifier-list shall consist of exactly one friend-type-specifier that is not a pack expansion. [ Example:template<class ...> struct C { struct Nested { }; }; template<class ... Us> struct S { template <typename ...Ts> friend class C<Ts>::Nested...; // error friend class C<Us>::Nested...; // OK };-- end example ]
Suggested resolution (2024-07-30):
Change in 13.1 [temp.pre] paragraph 5 as follows:
In a template-declaration, explicit specialization, or explicit instantiation, the init-declarator-list in the declaration shall contain at most one declarator. When such a declaration is used to declare a class template, no declarator is permitted. In a template-declaration whose declaration is a friend-type-declaration, the friend-type-specifier-list shall consist of exactly one friend-type-specifier; if it is a pack expansion (13.7.4 [temp.variadic]), any packs expanded by that pack expansion shall not have been introduced by the template-declaration. [ Example:template<class ...> struct C { struct Nested { }; }; template<class ... Us> struct S { template <typename ...Ts> friend class C<Ts>::Nested...; // error friend class C<Us>::Nested...; // OK };-- end example ]
The above resolution allows the following example:
template<class ... Us> struct S { template<class T> friend class C<T, Us>::Nested...; };
CWG was not convinced the above example was intended to be supported by paper P2893R3, which introduced pack expansions for friend declarations.
(From submissions #586 and #593.)
Consider:
struct C { template <typename> friend class Foo, int; };
This is obviously nonsense, but is not prohibited by the wording.
Also consider:
struct S { template <typename T> friend class Foo<T>::Nested; // OK; see 13.7.5 [temp.friend] paragraph 5 template <typename ...Ts> friend class Foo<Ts>::Nested...; // makes no sense };
History | |||
---|---|---|---|
Date | User | Action | Args |
2024-08-23 21:07:52 | admin | set | messages: + msg7809 |
2024-08-17 07:39:11 | admin | set | messages: + msg7802 |
2024-08-17 07:39:11 | admin | set | status: open -> review |
2024-07-30 22:16:57 | admin | set | messages: + msg7779 |
2024-04-30 00:00:00 | admin | create |