C++ 如何对带有约束的模板类使用友元声明

C++ 如何对带有约束的模板类使用友元声明,c++,friend,c++20,c++-concepts,C++,Friend,C++20,C++ Concepts,对于C++20,我们打算提出一些概念,一些编译器已经提供了一些早期的实现。我们在模板类的友元声明中遇到了一些问题,其中参数具有约束。经过一些自我反省和尝试在标准草案和相关文件中找到任何东西后,我们对什么是可能的和/或正确的并不明智 我们已经尝试了一个标准的想法,一个会找到一个解决方案,但没有得到任何适用于所有编译器的想法,或者一个来自标准的正式答案,这可能只是阅读正确的搜索结果带来的厄运 我们尝试的是在模板类和它自己之间创建一个朋友关系,使模板的所有其他实例化成为朋友 原始版本看起来像 temp

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

我们已经尝试了一个标准的想法,一个会找到一个解决方案,但没有得到任何适用于所有编译器的想法,或者一个来自标准的正式答案,这可能只是阅读正确的搜索结果带来的厄运

我们尝试的是在模板类和它自己之间创建一个朋友关系,使模板的所有其他实例化成为朋友

原始版本看起来像

template <typename T> concept Constraint = true;

template <Constraint T>
class A { };

struct B {
    template <typename>
    friend class A;
};
模板概念约束=true;
模板
A类{};
结构B{
模板
A级朋友;
};
这可以在gcc中编译,但既不能在clang中编译,也不能在最新的MSVC预览编译器中编译

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

template <typename T> concept Constraint = true;

template <Constraint T>
class A { };

struct B {
    template <Constraint>
    friend class A;
};
模板概念约束=true;
模板
A类{};
结构B{
模板
A级朋友;
};
这看起来是一种很自然的方式,因为无论如何只能通过满足约束来实例化friend

这通过了gcc,clang对此不满意,MSVC对声明没有问题,但在实际尝试使用它时失败了。它抱怨约束没有得到满足,这是不正确的

还有一种方法是将一些类ID放入好友声明中,即

template <typename T> concept Constraint = true;

template <Constraint T>
class A { };

struct B {
    template <Constraint U>
    friend class A;
};
模板概念约束=true;
模板
A类{};
结构B{
模板
A级朋友;
};
这与上一次尝试的结果相同。 到目前为止,我们还不能想出一个真正有效的语法(如果可能的话)。 如果不使用约束,使用SFINAE技巧,只使用“typename”,那么它将按预期工作


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

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

模板概念约束=true;
模板
A类{};
结构B{
A类模板;
};
这应该是
A
的所有专业化的朋友
typename
可能不正确,因为这与
A
的声明不匹配。我不认为我们有具体的措辞,但这似乎是明确的意图


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

谢谢你的回答,这也是我所期望的。不过,我对clang语句感到惊讶,我们无法使它对clang起作用。我们对gcc行为有了新的认识。MSVC支持最新预览版本中的概念,即如果使用std:c++latest选项,则从MSVC 19.3.0 preview 3开始。还没有实现所有功能。这就是为什么现在还没有正式的std:C++20选项。我只是看了看你的答案,发现它与问题略有不同。@H.Gutsche它与问题有何不同?那么问题是什么?我刚才看了你的答案,发现它与问题不同。我们不想和其他班级交朋友,但我们想和自己交朋友,也就是说,如果你的B变为A会发生什么?朋友发生在其朋友的声明范围内。尝试向当前正在声明的模板的未指定实例声明朋友。现在我完全困惑了,因为我意识到它目前的状况并不是我问的问题。你编辑了吗???@H.Gutsche是的,我编辑了这个问题,使它由真实的代码而不是随机的点组成,使它成为一个更好的问题。在
B
friending
A
A
friending
A
之间没有关系,正确的语法不会改变,而且两个编译器都是如此。
template <typename T> concept Constraint = true;

template <Constraint T>
class A { };

struct B {
    template <Constraint> friend class A;
};