C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Extending Friendship to Nested Template Class Instantiation

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
ghickman@acm.org
Guest





PostPosted: Fri May 18, 2007 12:47 am    Post subject: Extending Friendship to Nested Template Class Instantiation Reply with quote



In the following code, Container::Element_arena has access to
Container::Element's private constructor because Conainers are friends
of their Elements:

Scenario #1

class Container;

class Element {
public:
friend class Container;
private:
Element();
};

class Container {
private:
struct Element_arena {
Element* construct() { return new Element(); }
};
Element_arena arena;

public:
Element* make_inner() { return arena.construct(); }
};

If we wanted to apply this Container / Element design pattern to many
different application types, it might be nice to capture the arena
functionality in a template class Arena<T> to be reused in the
implementation of many different kinds of containers. However, the
compiler won't extend a Container's friendship privileges to an
internal (i.e., nested within the Container class definition)
instantiation of Arena<T>. In other words, given the following
changes:

Scenario #2

template<class T>
class Arena {
public:
T* construct() { return new T(); }
};

class Container {
private:
Arena<Element> arena;
public:
Element* make_inner() { return arena.construct(); }
};

Element::Element() is inaccessible to Arena<Element>::construct() even
though Arena<Element> is instantiated within the scope of a
Container. Clearly we wouldn't want arbitrary instantations of
Arena<Element> to have access to an Element's private parts, but it
"seems intuitive" that the compiler could discern Arena<Element>'s
context and allow Scenario#2 above.

Can anyone comment on why this doesn't (or can't) work within the
current rules?

Thanks,
Greg


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
uglystone
Guest





PostPosted: Fri May 18, 2007 8:11 am    Post subject: Re: Extending Friendship to Nested Template Class Instantiat Reply with quote



{ Edits: quoted signature and quoted clc++m comment removed. Tip: most
newsreader programs do that automatically (Google doesn't). -mod }

On May 18, 8:47 am, "ghick...@acm.org" <jghick...@gmail.com> wrote:
Quote:
In the following code, Container::Element_arena has access to
Container::Element's private constructor because Conainers are friends
of their Elements:

Scenario #1

class Container;

class Element {
public:
friend class Container;
private:
Element();

};

class Container {
private:
struct Element_arena {
Element* construct() { return new Element(); }
};
Element_arena arena;

public:
Element* make_inner() { return arena.construct(); }

};

If we wanted to apply this Container / Element design pattern to many
different application types, it might be nice to capture the arena
functionality in a template class Arena<T> to be reused in the
implementation of many different kinds of containers. However, the
compiler won't extend a Container's friendship privileges to an
internal (i.e., nested within the Container class definition)
instantiation of Arena<T>. In other words, given the following
changes:

Scenario #2

template<class T
class Arena {
public:
T* construct() { return new T(); }

};

class Container {
private:
Arena<Element> arena;
public:
Element* make_inner() { return arena.construct(); }

};

Element::Element() is inaccessible to Arena<Element>::construct() even
though Arena<Element> is instantiated within the scope of a
Container. Clearly we wouldn't want arbitrary instantations of
Arena<Element> to have access to an Element's private parts, but it
"seems intuitive" that the compiler could discern Arena<Element>'s
context and allow Scenario#2 above.

Can anyone comment on why this doesn't (or can't) work within the
current rules?

template<typename T>
class Arena;
class Element {
template<typename T>
friend class Arena;
private:
Element(){}
};

template<class T>
class Arena {
public:
T* construct() { return new T();; }
};


class Container {
private:
Arena<Element> arena;
public:
Element* make_inner() { return arena.construct(); }
};



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
ghickman@acm.org
Guest





PostPosted: Fri May 18, 2007 4:15 pm    Post subject: Re: Extending Friendship to Nested Template Class Instantiat Reply with quote



On May 18, 3:11 am, uglystone <zhaoj...@gmail.com> wrote:
Quote:

template<typename T
class Arena;
class Element {
template<typename T
friend class Arena;
private:
Element(){}

};

Unfortunately this solution isn't equivalent to the original non-
template version because it enables any user to gain access the
Element's constructor. My goal was for Container (and its nested
members) to be Element's only friend, but perhaps I didn't make that
clear in my original post.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Daniel Krügler
Guest





PostPosted: Fri May 18, 2007 4:17 pm    Post subject: Re: Extending Friendship to Nested Template Class Instantiat Reply with quote

On 18 Mai, 10:11, uglystone <zhaoj...@gmail.com> wrote:
Quote:
template<typename T
class Arena;
class Element {
template<typename T
friend class Arena;
private:
Element(){}

};

There is no good reason to grant friendship
for *every* instanciation of Arena. The most
simple and probably wanted scenario is this one,
I guess:

template<typename>
class Arena;

class Element {
friend class Arena<Element>;
private:
Element(){}
};

Greetings from Bremen,

Daniel Krügler



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Daniel Krügler
Guest





PostPosted: Fri May 18, 2007 4:21 pm    Post subject: Re: Extending Friendship to Nested Template Class Instantiat Reply with quote

On 18 Mai, 02:47, "ghick...@acm.org" <jghick...@gmail.com> wrote:
Quote:
class Container;

class Element {
public:
friend class Container;
private:
Element();

};

class Container {
private:
struct Element_arena {
Element* construct() { return new Element(); }
};
Element_arena arena;

public:
Element* make_inner() { return arena.construct(); }

};

If we wanted to apply this Container / Element design pattern to many
different application types, it might be nice to capture the arena
functionality in a template class Arena<T> to be reused in the
implementation of many different kinds of containers. However, the
compiler won't extend a Container's friendship privileges to an
internal (i.e., nested within the Container class definition)
instantiation of Arena<T>. In other words, given the following
changes:

Scenario #2

template<class T
class Arena {
public:
T* construct() { return new T(); }

};

class Container {
private:
Arena<Element> arena;
public:
Element* make_inner() { return arena.construct(); }

};

Element::Element() is inaccessible to Arena<Element>::construct() even
though Arena<Element> is instantiated within the scope of a
Container. Clearly we wouldn't want arbitrary instantations of
Arena<Element> to have access to an Element's private parts, but it
"seems intuitive" that the compiler could discern Arena<Element>'s
context and allow Scenario#2 above.

I don't think that the compiler should extend friendship
as you whish, because this would totally break the
"access-security" system of C++. Basically you seem to
demand that friendship should be extended to *every type*
that is used as a member of some friend class. This makes
no real sense, because types can be used everywhere (if I
have access to them at this place), so why should we
begin to create a web of friendship-relations to some class,
which often is used as member (or base class?) of some
other class? Please note, that you changed drastically the
situation, by factoring Arena *out* of the container. Arena
just had friend access to Element, because Arena was a
member class (nested class) and not just a member of some
arbitrary type! To create a more reasonable access-right
chain, we start by granting friendship from Element to
Arena<Element>:

template<class>
class Arena;

class Element {
friend class Arena<Element>;
private:
Element();
};

template<class T>
class Arena {
public:
T* construct() { return new T(); }
};

This has of course the effect, that everyone can
simply create an Element by using an instance of
Arena, because Arena is a public available class.
We can create a workaround for this situation by
adding one further layer of indirection, i.e. by
restricting Arena's access granting of member
construct to only to a dedicated ArenaContainer:

template<class>
class ArenaContainer;

template<class T>
class Arena {
private:
friend class ArenaContainer<T>;
T* construct() { return new T(); }
};

template<class T>
class ArenaContainer {
private:
Arena<T> arena;
public:
T* make_inner() { return arena.construct(); }
};

Now you need at least a ArenaContainer<Element>
to legally create an Element instance. Several
adaptions are possible: E.g. if you always need
inheritance to specialize ArenaContainer, you
could make make_inner protected (and either
provide a protected d'tor or a virtual one).
Derived classes could then decide to "publish"
make_inner (by means of a using-declaration) or
not.

Greetings from Bremen,

Daniel Krügler



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
ghickman@acm.org
Guest





PostPosted: Sat May 19, 2007 12:04 am    Post subject: Re: Extending Friendship to Nested Template Class Instantiat Reply with quote

On May 17, 7:47 pm, "ghick...@acm.org" <jghick...@gmail.com> wrote:

Quote:
Can anyone comment on why this doesn't (or can't) work within the
current rules?

As often happens, it became obvious to me after taking a step back
from the code that the compiler has no choice but to interpret
Arena<Element> as the one and the same type regardless of where it's
instantiated. So I'm left feeling a little foolish that I posed the
question in that way. :O

Quote:
If we wanted to apply this Container / Element design pattern to many
different application types, it might be nice to capture the arena
functionality in a template class Arena<T> to be reused in the
implementation of many different kinds of containers. However, the
compiler won't extend a Container's friendship privileges to an
internal (i.e., nested within the Container class definition)
instantiation of Arena<T>.

Nevertheless, I'm still looking for a solution to this problem,
namely: Is there a way to avoid having to rewrite
Container::Element_arena by hand for each unique container? Of
course, I considered making Arena<Element> a friend of Element (as
suggested in another post) unnacceptable because that gives any user
the ability to construct an Element, and that is something only a
Container should be able to do.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Daniel Krügler
Guest





PostPosted: Sat May 19, 2007 1:38 pm    Post subject: Re: Extending Friendship to Nested Template Class Instantiat Reply with quote

On 19 Mai, 02:04, "ghick...@acm.org" <jghick...@gmail.com> wrote:
Quote:
Nevertheless, I'm still looking for a solution to this problem,
namely: Is there a way to avoid having to rewrite
Container::Element_arena by hand for each unique container? Of
course, I considered making Arena<Element> a friend of Element (as
suggested in another post) unnacceptable because that gives any user
the ability to construct an Element, and that is something only a
Container should be able to do.

You haven't read my second answer properly, have you?
I demonstrated how this could be done by using Arena as
a potential creator for any elements by delegation to an
actual ArenaContainer template. You did not explain why
this approach did not fulfill your requirements.

Greetings from Bremen,

Daniel Krügler



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
ghickman@acm.org
Guest





PostPosted: Sun May 20, 2007 11:46 pm    Post subject: Re: Extending Friendship to Nested Template Class Instantiat Reply with quote

On May 19, 8:38 am, Daniel Krügler <daniel.krueg...@googlemail.com>
wrote:

Quote:
You haven't read my second answer properly, have you?

Thank you for posting. I read your comments, but I've had two posts
rejected by moderators in this thread; the first for "under-quoting"
and the latter for "over-quoting", and I've been out of town for a
couple of days since then too.

Quote:
I demonstrated how this could be done by using Arena as
a potential creator for any elements by delegation to an
actual ArenaContainer template. You did not explain why
this approach did not fulfill your requirements.

A set of cooperating templates does appear to be the key to a workable
approach. However, it didn't occur to me to parameterize a single
container class because the containers are very application-specific
and often quite different from one another. It's not clear to me how
to specify ArenaContainer<T> in a way that applies equally to all of
my containers, but I'll keep the idea in mind.

Thanks for responding and I apologize for my apparent lack of response
to your earlier posts.

-Greg



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
ghickman@acm.org
Guest





PostPosted: Sun May 20, 2007 11:46 pm    Post subject: Re: Extending Friendship to Nested Template Class Instantiat Reply with quote

On May 18, 11:21 am, Daniel Krügler <daniel.krueg...@googlemail.com>
wrote:

Quote:
I don't think that the compiler should extend friendship
as you whish, because...types can be used everywhere...

Of course you're right; I only realized how silly the suggestion was
after I posted. The compiler has no choice but to interpret
Arena<Element> as the same class no matter where it's instantiated.



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Matt Messina
Guest





PostPosted: Tue May 22, 2007 3:40 am    Post subject: Re: Extending Friendship to Nested Template Class Instantiat Reply with quote

ghickman (AT) acm (DOT) org <jghickman (AT) gmail (DOT) com> wrote:
Quote:
class Container;

class Element {
public:
friend class Container;
private:
Element();

};

template<class T
class Arena {
public:
T* construct() { return new T(); }
};

class Container {
private:
Arena<Element> arena;
public:
Element* make_inner() { return arena.construct(); }
};

Element::Element() is inaccessible to Arena<Element>::construct() even
though Arena<Element> is instantiated within the scope of a
Container. Clearly we wouldn't want arbitrary instantations of
Arena<Element> to have access to an Element's private parts, but it

I don't know about "clearly," but I'll take your word that you have
good reasons to reject making Arena<Element> a friend of Element.

Maybe you should separate memory allocation from object
initialization. You can have Arena<> allocate memory and have
Container use placement new to construct the Element at that memory
location.

#include <cstdlib>

template<class T>
class Arena
{
public:
void* alloc()
{ return std::malloc(sizeof(T)); }
void dealloc(void* p)
{ std::free(p); }
};

#include <new>

class Container;

class Element
{
friend class Container;
private:
Element() { }
};

class Container
{
private:
Arena<Element> arena;
public:
Element* make_inner()
{ return new (arena.alloc()) Element; }
void destroy_inner(Element* e)
{ e->~Element(); arena.dealloc(e); }
};

Replace malloc() and free() with whatever allocation mechanism is
needed.
--
Matt Messina
messina (AT) yahoo (DOT) com


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
 


Powered by phpBB © 2001, 2006 phpBB Group