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

标签 c++ friend c++20 c++-concepts

对于 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;
};

这看起来是一种自然的做法,因为 friend 只能在满足约束的情况下实例化。

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

有人还提出将一些类 ID 放入 friend 声明中,即

template <typename T> concept Constraint = true;

template <Constraint T>
class A { };

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

这与之前的尝试结果相同。 到目前为止,我们还没有想出一个真正有效的语法(如果可能的话)。 如果不使用约束并使用 SFINAE 技巧并仅使用“typename”,它会按预期工作。

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

最佳答案

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

template <typename T> concept Constraint = true;

template <Constraint T>
class A { };

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

这应该有助于A 的所有特化。 typename 是不正确的,因为它与 A 的声明不匹配。我不认为我们对此有具体的措辞,但这似乎是明确的意图。

gcc 和 clang 都接受这个版本(demo),而 compiler-explorer 上的 MSVC 版本还没有实现概念。

关于c++ - 如何对带有约束的模板类使用友元声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58102963/

相关文章:

c++ - placeNumbers 应返回数字的顺序,以满足 bool 值 vector 中编码的条件

c++ - 整数如何存储在内存中?

C++:x64 不推荐使用 A2W 宏 - 替代方案?

c++ - 基于概念的模板成员函数重载

c++ - 可以将模板化的 lambda 存储到 std::function 中吗?

c++ - 为菜单系统实现 lua 回调

c++ - 在类中定义主函数

c++ - 在类中实现并在全局命名空间中调用的友元函数

C++类,友元运算符与外部运算符有什么区别

c++ - static_assert 参数包中每个参数的大小