Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 653
Edward Strange Avatar asked Feb 03 '11 20:02

Edward Strange


People also ask

Can template function friends?

One-to-one: A template function instantiated with one set of template arguments may be a friend to one template class instantiated with the same set of template arguments. This is also the relationship between a regular non-template class and a regular non-template friend function.

Can we pass Nontype parameters to templates?

Template classes and functions can make use of another kind of template parameter known as a non-type parameter. A template non-type parameter is a template parameter where the type of the parameter is predefined and is substituted for a constexpr value passed in as an argument.

What is a template parameter?

In UML models, template parameters are formal parameters that once bound to actual values, called template arguments, make templates usable model elements. You can use template parameters to create general definitions of particular types of template.

How do you add a friend to a class in C++?

Declaration of a friend function in C++class class_name { friend data_type function_name(arguments/s); //syntax of friend function. }; In the above declaration, the keyword friend precedes the function. We can define the friend function anywhere in the program like a normal C++ function.


2 Answers

You are correct about C++98/03. However C++0x (n3225 11.4/3) allows you to do this with this syntax:

friend Owner;

See if your compiler will let you do that. Try turning on C++0x support. Otherwise the workarounds are uglier:

struct Owner
{
    typedef Owner self;
};

...

Then depending on your compiler one of:

friend typename Owner::self;

or:

friend class Owner::self;
like image 154
Howard Hinnant Avatar answered Nov 15 '22 09:11

Howard Hinnant


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.

like image 37
Yochai Timmer Avatar answered Nov 15 '22 11:11

Yochai Timmer