Ad *_*d N 5 c++ templates friend c++11
我们在代码库中发现了令人惊讶的行为,其中友谊关系未能应用.(目前仅与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;
}
};
Run Code Online (Sandbox Code Playgroud)
在这里,Details声明FriendBis用其单个模板模板参数替换的实例化Element是它的friend.因此,以下客户端代码成功编译:
FriendBis<Element> fb1;
fb1.useDetails(Details());
Run Code Online (Sandbox Code Playgroud)
现在,让我们介绍一个额外的trait模板化类型,其目的是定义proto模板的模板别名Element:
struct trait
{
template <int N>
using proto = Element<N>;
};
Run Code Online (Sandbox Code Playgroud)
下面的客户端代码无法编译:
FriendBis<trait::proto> fb2;
fb2.useDetails(Details());
Run Code Online (Sandbox Code Playgroud)
这对我们来说是令人惊讶的,因为trait::proto它是别名Element,但是一个编译而另一个不编译.
FriendBis一个朋友的所有实例).别名模板与其别名的类型不同义:trait::proto并且Element是不同的类型。当 template-id 引用 的特化时,trait::proto 它相当于替换类型。简单地说,trait::proto不是Element,trait::proto<0> 而是 Element<0>。
回答您的问题:
是的,这是预期的行为
基本原理是别名类型可能比简单的复杂得多Element<N>,它可能类似于Element<ElementForInt<N+1>::value>. 那么映射是不明显的。
我无法立即想到解决方法。如果您想检查模板模板参数是否与其他模板相同并考虑别名模板,您可以检查两个名称的实例化是否具有相同的类型,例如std::is_same<T<0>, Element<0>>,但我不确定如何使其工作在朋友宣言中。