gpt4 book ai didi

c++ - 就友元而言,为什么别名模板与别名类型模板的处理方式不同?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:43:32 25 4
gpt4 key购买 nike

我们在我们的代码库中观察到一个令人惊讶的行为,其中未能应用友元关系。 (目前仅使用 Clang,版本 3.6 编译)

我们可以将其简化为这个最小的例子。假设我们有以下模板类定义:

template <int>
class Element
{};


// Forward declaration of FriendBis
template <template <int> class> class FriendBis;

class Details
{
friend class FriendBis<Element>;
int mValue = 41;
};

template <template <int> class>
class FriendBis
{
public:
void useDetails(const Details &aDetails)
{
aDetails.mValue;
}
};

这里,Details 声明 FriendBis 的实例化,其单个模板模板参数替换为 Element 是其 friend 。因此,以下客户端代码编译成功:

FriendBis<Element> fb1;
fb1.useDetails(Details());

问题

现在,让我们介绍额外的 trait 模板类型,其全部目的是将 proto 定义为 Element 模板的模板别名:

struct trait
{
template <int N>
using proto = Element<N>;
};

下面的客户端代码无法编译:

FriendBis<trait::proto> fb2;
fb2.useDetails(Details());

这让我们很惊讶,因为 trait::protoElement 的别名,但是一个编译而另一个不编译。

  • 这是预期的行为吗?
    • 如果是这样,这种限制的理由是什么?
    • 有解决办法吗? (同时保持有限的友元,而不是将 FriendBis 的所有实例化为 friend )。

最佳答案

别名模板与其别名的类型不是同义词:trait::protoElement是不同的类型。当模板 ID 引用 trait::proto 的特化时then 它等同于被替换的类型。简单地说,trait::proto不是 Element ,但是 trait::proto<0> Element<0> .

回答您的问题:

  • 是的,这是预期的行为

  • 理由是别名类型可能远比 Element<N> 复杂得多, 它可能类似于 Element<ElementForInt<N+1>::value> .这样映射就不明显了。

  • 我想不出一个解决方法。如果你想检查一个模板模板参数是否与其他模板相同考虑别名模板,你可以检查这两个名称的实例化是否具有相同的类型,例如std::is_same<T<0>, Element<0>> ,但我不确定您将如何在好友声明中实现这一点。

关于c++ - 就友元而言,为什么别名模板与别名类型模板的处理方式不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33480690/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com