We observed a surprising behaviour in our code base, where a friendship relation was failing to be applied. (It is currently compiled only with Clang, version 3.6)
We could reduce it to this minimal example. Let's imagine we have the following template class definitions:
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;
}
};
Here, Details
declares that the instantiation of FriendBis
with its single template template parameter substituted with Element
is its friend
. Because of that, the following client code compiles successfully:
FriendBis<Element> fb1;
fb1.useDetails(Details());
The problem
Now, let's introduce the additional trait
templated type, whose whole purpose is to define proto
as a template alias for the Element
template:
struct trait
{
template <int N>
using proto = Element<N>;
};
The client code below does not compile:
FriendBis<trait::proto> fb2;
fb2.useDetails(Details());
It is surprising to us, because trait::proto
is an alias for Element
, but one compiles while the other does not.
- Is this an expected behaviour ?
- If so, what is the rationale for this restriction ?
- Is there a workaround ? (while maintaining a restricted friendship, instead of making all instantiations of
FriendBis
a friend).