Search code examples
c++templatesfriend

Friending a template parameter


It's impossible to friend a template parameter because the standard disallows it. How might I get effectively the same thing then?

What I want is basically a type that is unusable outside the object which owns it. Why is rather beside the point but if you really must know, I'm trying to formulate a set of smart pointers that answer the problem of sharing an owned resource. Thus what I'm looking to do is something like so, if it worked:

template < typename T, typename Owner >
struct accessible_member
{
private:
  accessible_member() : val(T()) {}
  accessible_member(T const& t) : val(t) {}

  operator T& () { return val; }
  operator T const& () const { return val; }

  member_ptr<T> operator & () { return member_ptr<T>(val); }

  friend class Owner;
};

Thus a class can't hold this object as a member unless it declares itself the owner, and if it's silly enough to expose it as is, it will be impossible to use outside the class being so stupid.


Solution

  • You could use this, and then let all the owners inherit from Owner.

    You could then use Owner class to wrap privately the methods used in accessible_member.
    accessible_member is now accessible to Owner. Friend is not inherited, so you can supply (wrap) the necessary methods so all the classes that inherit Owner can use accessible_member.

    It's a 2 level solution but it keeps the level of encapsulation.

    template < typename U >
    struct Owner 
    {
       protected:
       accessible_member<U> newAccessible_member() { return accessible_member<U>(); }
       accessible_member<U> newAccessible_member(U const& u) { return accessible_member<U>(u); }
       .....
    
    };
    
    template < typename T >
    struct accessible_member
    {
    private:
      accessible_member() : val(T()) {}
      accessible_member(T const& t) : val(t) {}
    
      operator T& () { return val; }
      operator T const& () const { return val; }
    
      member_ptr<T> operator & () { return member_ptr<T>(val); }
    
    
      template < typename U> friend class Owner;
    };
    

    Then you can use the accessible_member indirectly in structs that inherit from Owner using the protected methods:

    struct Blah: Owner<int>
    {
       void Dosomething() {
           accessible_member<int> blah= newAccessible_member();
       }
    };
    

    Look at the last example at Template Friends.