 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
ghickman@acm.org Guest
|
Posted: Fri May 18, 2007 12:47 am Post subject: Extending Friendship to Nested Template Class Instantiation |
|
|
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
|
Posted: Fri May 18, 2007 8:11 am Post subject: Re: Extending Friendship to Nested Template Class Instantiat |
|
|
{ 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
|
Posted: Fri May 18, 2007 4:15 pm Post subject: Re: Extending Friendship to Nested Template Class Instantiat |
|
|
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
|
Posted: Fri May 18, 2007 4:17 pm Post subject: Re: Extending Friendship to Nested Template Class Instantiat |
|
|
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
|
Posted: Fri May 18, 2007 4:21 pm Post subject: Re: Extending Friendship to Nested Template Class Instantiat |
|
|
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
|
Posted: Sat May 19, 2007 12:04 am Post subject: Re: Extending Friendship to Nested Template Class Instantiat |
|
|
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
|
Posted: Sat May 19, 2007 1:38 pm Post subject: Re: Extending Friendship to Nested Template Class Instantiat |
|
|
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
|
Posted: Sun May 20, 2007 11:46 pm Post subject: Re: Extending Friendship to Nested Template Class Instantiat |
|
|
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
|
Posted: Sun May 20, 2007 11:46 pm Post subject: Re: Extending Friendship to Nested Template Class Instantiat |
|
|
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
|
Posted: Tue May 22, 2007 3:40 am Post subject: Re: Extending Friendship to Nested Template Class Instantiat |
|
|
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 |
|
 |
Powered by phpBB © 2001, 2006 phpBB Group
|