lundi 2 novembre 2015

Why would an Alias Template be treated differently than the aliased type when it comes to friendship?

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).

Aucun commentaire:

Enregistrer un commentaire