如何将友元声明用于具有约束的模板类

How to use friend declaration for template class with constraints

本文关键字:约束 友元 声明 用于      更新时间:2023-10-16

对于C++20概念,一些编译器已经为它提供了一些早期的实现。我们在模板类的友元声明中遇到了一些问题,其中参数具有约束。经过一些反省并试图在标准草案和相关文档中找到任何东西之后,我们对什么是可能的和/或正确的并不明智。

我们已经尝试了人们会想出的标准想法来找到解决方案,但没有得出任何适用于所有尝试过的编译器或标准中的正式答案的想法,这可能只是阅读正确的搜索结果的运气不好。

我们尝试在模板类和自身之间创建友元关系,使模板的所有其他实例化成为友元。

原始版本看起来像

template <typename T> concept Constraint = true;
template <Constraint T>
class A { };
struct B {
template <typename>
friend class A;
};

这在 gcc 中编译,但既不是在 clang 中编译,也不是最新的 MSVC 预览编译器

下一个尝试是使用友元声明中的约束,即

template <typename T> concept Constraint = true;
template <Constraint T>
class A { };
struct B {
template <Constraint>
friend class A;
};

这看起来是一种自然的方式,因为朋友只有在满足约束的情况下才能实例化。

这在 gcc 中通过,clang 对此不满意,MSVC 可以声明,但在实际尝试使用它时失败。它抱怨说,这些限制没有得到满足,这是不正确的。

人们还想出将一些类 ID 放入朋友声明中,即

template <typename T> concept Constraint = true;
template <Constraint T>
class A { };
struct B {
template <Constraint U>
friend class A;
};

这会导致与上一次尝试相同的结果。 到目前为止,我们还无法提出实际有效的语法(如果可能的话(。 如果不使用约束并使用 SFINAE 技巧并仅使用"类型名",则它可以按预期工作。

如果有人知道如何使用实际的 C++20 功能或实际描述这种情况的指针来修复它,将不胜感激。我们知道我们可以只使用二传手和接球手,但这不是重点。

我很确定这是正确的版本(即您的第二或第三选项(:

template <typename T> concept Constraint = true;
template <Constraint T>
class A { };
struct B {
template <Constraint> friend class A;
};

这应该与A的所有专业交朋友。typename会不正确,因为这与A声明不匹配。我认为我们对此没有具体的措辞,但这似乎是明确的意图。

gcc 和 clang 都接受这个版本(demo(,而编译器资源管理器上的 MSVC 版本根本没有实现概念。