[paired ptr] Proposing a new smart pointer object for managing bidirectional relationships between objects

Dear all, I have been working on a proposal for a useful utility for managing non hierarchal, bi-directional relationships between objects and as a useful tool in object composition. This utility is in the form of a type of templated smart pointer that can connect to one single other pointer and manage the relationship between the two pointers. This paired_ptr object is intended for use as a member of (or at least contained within) a user defined object and is conceptualized from the needs of object composition. Prototype source code, a usage example and brief documentation is available here: http://www.boostpro.com/vault/index.php?action=downloadfile&filename=paired_ptr.zip&directory=& Doumentation only is available here: (this is a google doc and is continually being updated) http://docs.google.com/View?id=dc33pnfx_442s22z7d6 I am posting here in the hope it will generate suitable interest that it may be worth developing as a full library for submission. Best wishes, Dan

Dan Walters wrote:
Doumentation only is available here: (this is a google doc and is continually being updated)
http://docs.google.com/View?id=dc33pnfx_442s22z7d6
I am posting here in the hope it will generate suitable interest that it may be worth developing as a full library for submission.
The idea is interesting, but I'm not sure whether I'd use it. The example you provide is not compelling. I'd like to see some real, useful examples to motivate the need for paired_ptr. FYI: I only looked at the document, not the code, when generating the following comments. You asked in the document, so I'll mention that Boost doesn't use mixed case and doesn't prepend "C" to class names. You should adjust your examples accordingly. None of the code appears to be formatted properly. Your "Usage" section should use initialization rather than assignment for paired_cat and paired_dog. Indeed, from the surrounding text, it would seem that calling set_owner() is the only way to indicate the owner and that means it is possible to not specify an owner. It would be better if the constructor required an owner so the user is forced to initialize the instance with one. Doing so will eliminate the "unfortunate" sentence. (Note that you can still support set_owner() to permit changing ownership, and that the instance can be initialized with a null pointer, but that initializing from a null pointer and not calling set_owner() later is a user error of commission not omission.) The type is named "paired_ptr" so why does "pair" appear in member functions like "connect_pair" and "disconnect_pair?" Looking at the "Callback Functions" section, it appears that constructor overloads accepting the owner plus either or both of the callback functions would be in order versus requiring individual function calls. The callbacks should be boost::functions for maximum flexibility. You have assumed the size of a member function pointer is the same as an ordinary pointer, but that's a false assumption. It depends upon platform. Rather than a fat and skinny version of paired_ptr, perhaps the callbacks could be stored in a separately allocated object that is created only when needed. Indeed, using SBO you could keep the size to just two pointers. When there are no callbacks, use just the data members, but when there are callbacks, store everything in a separate allocation. (If the two data members point to the same address, it will be the address of memory allocated on the free store to hold two object pointers and two member function pointers. If they refer to different addresses, then there is no free store allocation and there are no callbacks.) The callbacks should know the paired_ptr invoking them, because a legitimate reaction might be to modify the paired_ptr's state and using boost::function, the callback may not be a member function or there may be more than one in a UDT and the callback would need to disambiguate. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Hi Rob, Thank your for your feedback, i am finding it very useful.
The idea is interesting, but I'm not sure whether I'd use it. The example you provide is not compelling. I'd like to see some real, useful examples to motivate the need for paired_ptr.
I will construct some better examples to prove its worth. There is already another example within the source package.
You asked in the document, so I'll mention that Boost doesn't use mixed case and doesn't prepend "C" to class names. You should adjust your examples accordingly.
I will amend the example.
None of the code appears to be formatted properly.
And I will amend the documentation.
Your "Usage" section should use initialization rather than assignment for paired_cat and paired_dog. Indeed, from the surrounding text, it would seem that calling set_owner() is the only way to indicate the owner and that means it is possible to not specify an owner. It would be better if the constructor required an owner so the user is forced to initialize the instance with one. Doing so will eliminate the "unfortunate" sentence.
I was using initialization however this does cause a warning c4355 inside the user defined class constructor. warning C4355: 'this' : used in base member initializer list I could disable the warning in the paired_ptr header as the usage is safe however this is fairly bad practice as it would result in the users project having the warning disabled, and probably against boost guidelines. Thus I opted for an initialization function.
The type is named "paired_ptr" so why does "pair" appear in member functions like "connect_pair" and "disconnect_pair?"
I take it that you are suggesting a more suitable name would be "connect_to_paired_ptr"? That would be more descriptive.
Looking at the "Callback Functions" section, it appears that constructor overloads accepting the owner plus either or both of the callback functions would be in order versus requiring individual function calls.
I will extend this function.
The callbacks should be boost::functions for maximum flexibility.
The problem here comes where I am specifying member functions to be called back. boost::function does not support member functions and recommends std::bind1st functionality. This results in three options: 1. use member functions in the current manner. 2. use function objects using boost::function 3. use bind1st and support both at the cost of less tidy code. There is a clear advantage in specifying member functions rather than say, void callback_connect(owner_type* p_owner, paired_ptr<owner_type,other_type>* p_paired_ptr) as it is much tidier to program and removes the need of global functions or function objects. On the other hand, Your point of using boost::function is persuasive as function objects are not a bad alternative and will extend the ability of callback to allow other functions rather than just member functions. I have a feeling that implementing this will mean the user implementation will be difficult. I will take a second look.
You have assumed the size of a member function pointer is the same as an ordinary pointer, but that's a false assumption. It depends upon platform.
Good to know.
Rather than a fat and skinny version of paired_ptr, perhaps the callbacks could be stored in a separately allocated object that is created only when needed. Indeed, using SBO you could keep the size to just two pointers. When there are no callbacks, use just the data members, but when there are callbacks, store everything in a separate allocation. (If the two data members point to the same address, it will be the address of memory allocated on the free store to hold two object pointers and two member function pointers. If they refer to different addresses, then there is no free store allocation and there are no callbacks.)
That is a very good suggestion for keeping size down, and keeping paired_ptr objects with callback inter operable with paired_ptr objects without callback.
The callbacks should know the paired_ptr invoking them, because a legitimate reaction might be to modify the paired_ptr's state and using boost::function, the callback may not be a member function or there may be more than one in a UDT and the callback would need to disambiguate.
I have already added this functionality since posting here :) But again, the callbacks cannot have the option of being either a normal function or member function as the parameter lists are different. Perhaps the correct decision is for callback functions to be static member functions or regular functions via boost::function. Thanks again for your review Rob, it has given me lots to think about! I hope my comments help clarify some holes in my documentation? Best wishes, Dan

Dan Walters wrote:
Your "Usage" section should use initialization rather than assignment for paired_cat and paired_dog. Indeed, from the surrounding text, it would seem that calling set_owner() is the only way to indicate the owner and that means it is possible to not specify an owner. It would be better if the constructor required an owner so the user is forced to initialize the instance with one. Doing so will eliminate the "unfortunate" sentence.
I was using initialization however this does cause a warning c4355 inside the user defined class constructor. warning C4355: 'this' : used in base member initializer list
I could disable the warning in the paired_ptr header as the usage is safe however this is fairly bad practice as it would result in the users project having the warning disabled, and probably against boost guidelines. Thus I opted for an initialization function.
That's an MSVC-specific warning. Use pragmas push, disable, and pop, conditionally compiled for MSVC, to manage that warning.
The type is named "paired_ptr" so why does "pair" appear in member functions like "connect_pair" and "disconnect_pair?"
I take it that you are suggesting a more suitable name would be "connect_to_paired_ptr"? That would be more descriptive.
No. I was implying "connect" and "disconnect" for those two. There are other possibilities to explore, too. You could use assignment in lieu of "connect," but then it would be difficult to distinguish between connecting and copy assignment. (The "disconnect" complement would be "release.") You could use operator +=() for "connect" and operator -=() for "disconnect," but I think those will raise more eyebrows than their worth. Anyway, I wanted less repetitive not more verbose.
The callbacks should be boost::functions for maximum flexibility.
The problem here comes where I am specifying member functions to be called back. boost::function does not support member functions and recommends std::bind1st functionality. This results in three options:
Yes, that's an unfortunate side effect.
1. use member functions in the current manner. 2. use function objects using boost::function 3. use bind1st and support both at the cost of less tidy code.
There is a clear advantage in specifying member functions rather than say, void callback_connect(owner_type* p_owner, paired_ptr<owner_type,other_type>* p_paired_ptr) as it is much tidier
Don't assume that the object type for the callback member function pointer is the owner type.
to program and removes the need of global functions or function objects. On the other hand, Your point of using boost::function is persuasive as function objects are not a bad alternative and will extend the ability of callback to allow other functions rather than just member functions. I have a feeling that implementing this will mean the user implementation will be difficult. I will take a second look.
Using Boost.Function makes your callback support more flexible, which makes it more useful to users. However, supporting member functions is less clean as you mention. How about the following: - Support boost::function for maximum flexibility - Provide a member function template that takes a T * and a T member function pointer That makes the calling syntax as simple as possible while maximizing flexibility.
The callbacks should know the paired_ptr invoking them, because a legitimate reaction might be to modify the paired_ptr's state and using boost::function, the callback may not be a member function or there may be more than one in a UDT and the callback would need to disambiguate.
I have already added this functionality since posting here :) But again, the callbacks cannot have the option of being either a normal function or member function as the parameter lists are different. Perhaps the correct decision is for callback functions to be static member functions or regular functions via boost::function.
I fail to understand the problem. In each case you are invoking a functor with a reference to a paired_ptr. (You could even support overloading for const and non-const access.) What you need is type erasure to make the callback invocation ignorant of how the underlying function is invoked. IOW, you want a member function pointer invocation, via Boost.Function, say, to look just like calling a non-member function pointer or function object. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Zitat von "Stewart, Robert" <Robert.Stewart@sig.com>:
Dan Walters wrote:
Doumentation only is available here: (this is a google doc and is continually being updated)
http://docs.google.com/View?id=dc33pnfx_442s22z7d6
I am posting here in the hope it will generate suitable interest that it may be worth developing as a full library for submission.
reminds me of UML class diagram bi-directional associations. if this makes sense for C++ (I'm not sure) you also might want to consider other types of associations, e.g. n-ary associations that are automatically kept consistent on both ends of the association.

Dan Walters-2 wrote:
Dear all,
I have been working on a proposal for a useful utility for managing non hierarchal, bi-directional relationships between objects and as a useful tool in object composition.
This utility is in the form of a type of templated smart pointer that can connect to one single other pointer and manage the relationship between the two pointers.
This paired_ptr object is intended for use as a member of (or at least contained within) a user defined object and is conceptualized from the needs of object composition.
Prototype source code, a usage example and brief documentation is available here:
http://www.boostpro.com/vault/index.php?action=downloadfile&filename=paired_ptr.zip&directory=&
Doumentation only is available here: (this is a google doc and is continually being updated)
http://docs.google.com/View?id=dc33pnfx_442s22z7d6
I am posting here in the hope it will generate suitable interest that it may be worth developing as a full library for submission.
Best wishes,
Dan _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Hi, I don't know why I don't like the name paired_ptr, one_to_one_ptr could be an alternative. I will see this class as one more in a Association library that could include other kind of associations, as one_to_many, many_to_one, many_to_many,... class CCat CDog rex; CCat kitty; As no one side of the association is more important than the other maybe a non-member function could be more adequate. The connection between two objects can be established as so connect(rex.paired_cat, kitty.paired_dog); //connections can be severed at either end disconnect(kitty.paired_dog); have you think about adding a mixin paired_ptr that can be used as base class and as such don't need to manage with the owner initialization? class CCat; class CDog; class CDog : public one_to_one_ptr<CDog, CCat> { ... }; class CCat : public one_to_one_ptr<CCat,CDog> { ... }; Now the connection can be done directly connect(rex, kitty); one_to_one_ptr<T,U> could define a method to get the pointed U, get<U> that can be used like get<CCat>(rex); or rex.get<CCat>(); Best, Vicente -- View this message in context: http://old.nabble.com/-paired-ptr--Proposing-a-new-smart-pointer-object-for-... Sent from the Boost - Dev mailing list archive at Nabble.com.

----- Original Message ----- From: "Dan Walters" <dan683@googlemail.com> To: <boost@lists.boost.org> Sent: Sunday, May 02, 2010 12:28 PM Subject: [boost] [paired ptr] Proposing a new smart pointer object formanaging bidirectional relationships between objects Dear all, I have been working on a proposal for a useful utility for managing non hierarchal, bi-directional relationships between objects and as a useful tool in object composition. This utility is in the form of a type of templated smart pointer that can connect to one single other pointer and manage the relationship between the two pointers. This paired_ptr object is intended for use as a member of (or at least contained within) a user defined object and is conceptualized from the needs of object composition. _______________________________________________ There is also Boost.Bimap. Even if this is more general than what you are trying to achieve, maybe it is worth reading the documentation. The advantage is that the CCat and the CDog classes can be independent one of each other. _____________________ Vicente Juan Botet Escribá http://viboes.blogspot.com/

Thanks again to Rob for the additional feedback, and Vincente and Strasse for your feedback also. I'll try to respond to all in one big message. Rob:
That's an MSVC-specific warning. Use pragmas push, disable, and pop, conditionally compiled for MSVC, to manage that warning
For MSVC, warning 4355 is disabled in the paired_ptr header.
No. I was implying "connect" and "disconnect" for those two.
After replying to you, I went back to the source and it was obvious shorter names were more appropriate, and have updated already to connect and disconnect function names.
Using Boost.Function makes your callback support more flexible, which makes it more useful to users.
Callback functions are now of type boost::function1<paired_ptr<T,U>*> where T is the owner type and U is the pointed to owner type. This works well as users can generate global functions to handle the callbacks, use static member functions, and even static member functions from other classes. Hence for member usage: class dog {public: static void connect_to_cat(paired_ptr<dog,cat>* p_paired_ptr) // paired_cat.set_connect_callback(&dog::connect_to_cat); { // to get the this pointer, use p_paired_ptr->owner() } }; After consideration, I think this is a much more robust and flexible solution.
Don't assume that the object type for the callback member function pointer is the owner type.
That was an ugly solution and another reason to use boost::function1<paired_ptr<T,U>*>
I fail to understand the problem. In each case you are invoking a functor with a reference to a paired_ptr. (You could even support overloading for const and non-const access.) What you need is type erasure to make the callback invocation ignorant of how the underlying function is invoked. IOW, you want a member function pointer invocation, via Boost.Function, say, to look just like calling a non-member function pointer or function object.
The problem is that to call a normal function, the arguments would be: void callback_function(<paired_ptr<T,U>* p_ptr); For a member function it would be: void callback_function(T* this, <paired_ptr<T,U>* p_ptr); Obviously, the this pointer is available in member functions and so is passed invisibly to the function. So the parameter lists are different and not inter-operable between global functions and member functions. This can be overcome using std::bind1st. I opt for settling for global functions and static member functions, as it is a simple and flexible solution. Thanks Rob, again your comments are gratefully received. Vicente:
I don't know why I don't like the name paired_ptr, one_to_one_ptr could be an alternative.
I will see this class as one more in a Association library
How about bi_ptr? The object is then clearly a bidirectional pointer. one_to_one still seems ambiguous to me. Infact, is this library even a pointer? It never manages memory in any way. Except for the -> operator and the get() function (like smart_ptrs) it doesn't really have any responsibilities that a pointer has, the name is only intended to make clear that it isn't the object itself. But a pointer is usually a container for a single object, and this is not a container. Maybe it is a reference? But this would confuse the -> operator and the get() function... that could include other kind of associations, as one_to_many, many_to_one, many_to_many,... While this immediately seems obvious, the one_to_one relationship is quite special. Here, both sides of the relationship share authority. A one to many or many to one relationship clearly has a single authoritative element - being the one rather than the many. How would these differ from a pointer container? And the many to many relationship is already dealt with in a way by the bimap library (as you later pointed out). The one-to-one relationship is a pointer to pointer, while any relationship involving a 'many' starts to become a container and in any container, there must be an authoritative element to manage the contents. Would it be possible for a group of elements to manage the pool that they reside in? Is this really useful in any way? To me, the one-to-one relationship is a special issue that can occur in the most simple of programs.
As no one side of the association is more important than the other maybe a non-member function could be more adequate. The connection between two objects can be established as so
connect(rex.paired_cat, kitty.paired_dog);
//connections can be severed at either end disconnect(kitty.paired_dog);
This is something I had already considered and have now wrapped paired_ptr.connect inside a global function as suggested, but have also left the paired_ptr.connect interface as a member also. I think both are useful, as the non-member function indicates the rationale of neither object being authoritative, while the connect member function indicates that either paired_ptr can initialize a connection.
have you think about adding a mixin paired_ptr that can be used as base class and as such don't need to manage with the owner initialization?
I had considered this. I think that as a member, the object is more useful as it represents a 'has' relationship rather than a 'is' relationship - composition is primary to the rationale. Consider the following: class person { paired_ptr<person,person> father; }; class person : public paired_ptr<person,person> { }; Obviously the inherited version poorly represents the concept of a father, as it suggests the person is a special type of a link between two people. It also limits the class to only one paired_ptr, and of only one pair of types. However, it would fix the issue of initializing the owner of the paired_ptr member.
one_to_one_ptr<T,U> could define a method to get the pointed U, get<U>
A dynamic_cast version? I like that idea very much.
There is also Boost.Bimap
Thanks for reminding me. In a way, this library is a light weight version of bimap as it acts as a bimap holding two single values, mapping the type on the left to the type on the right. The advantage of paired_ptr is that there is no left and right, simply two ends of a link. paired_ptr is also a LOT simpler and hence much easier to use. Thanks again Vicente, I found your feedback very useful. Strasser:
reminds me of UML class diagram bi-directional associations.
Thanks for pointing this out. I think that kind of relationship is a common requirement when programming and is so often worked around in a c++ environment.
if this makes sense for C++ (I'm not sure) you also might want to consider other types of associations, e.g. n-ary associations that are automatically kept consistent on both ends of the association.
As Vicente mentioned, there is bimap that is a very complete bidirectional container library. I see the scope of this library as managing the one-to-one relationship. It is a pointer rather than a container, and as such, completes a very very different role. It has spawned from my thoughts on composition and the limitations of directional ownership. Thanks again you all of you for the feedback, i have found it to be a huge help! I welcome any more comments :) Best wishes, Dan

----- Original Message ----- From: "Dan Walters" <dan683@googlemail.com> To: <boost@lists.boost.org> Sent: Tuesday, May 04, 2010 12:54 AM Subject: Re: [boost] [paired ptr] Proposing a new smart pointer objectformanaging bidirectional relationships between objects
Thanks again to Rob for the additional feedback, and Vincente and Strasse for your feedback also.
I'll try to respond to all in one big message.
Rob:
That's an MSVC-specific warning. Use pragmas push, disable, and pop, conditionally compiled for MSVC, to manage that warning
For MSVC, warning 4355 is disabled in the paired_ptr header.
No. I was implying "connect" and "disconnect" for those two.
After replying to you, I went back to the source and it was obvious shorter names were more appropriate, and have updated already to connect and disconnect function names.
Using Boost.Function makes your callback support more flexible, which makes it more useful to users.
Callback functions are now of type boost::function1<paired_ptr<T,U>*> where T is the owner type and U is the pointed to owner type. This works well as users can generate global functions to handle the callbacks, use static member functions, and even static member functions from other classes. Hence for member usage:
class dog {public: static void connect_to_cat(paired_ptr<dog,cat>* p_paired_ptr) // paired_cat.set_connect_callback(&dog::connect_to_cat); { // to get the this pointer, use p_paired_ptr->owner() } };
After consideration, I think this is a much more robust and flexible solution.
Don't assume that the object type for the callback member function pointer is the owner type.
That was an ugly solution and another reason to use boost::function1<paired_ptr<T,U>*>
I fail to understand the problem. In each case you are invoking a functor with a reference to a paired_ptr. (You could even support overloading for const and non-const access.) What you need is type erasure to make the callback invocation ignorant of how the underlying function is invoked. IOW, you want a member function pointer invocation, via Boost.Function, say, to look just like calling a non-member function pointer or function object.
The problem is that to call a normal function, the arguments would be:
void callback_function(<paired_ptr<T,U>* p_ptr);
For a member function it would be:
void callback_function(T* this, <paired_ptr<T,U>* p_ptr);
Obviously, the this pointer is available in member functions and so is passed invisibly to the function. So the parameter lists are different and not inter-operable between global functions and member functions. This can be overcome using std::bind1st.
I think this is what Rob is saying. You need just to define the prototype for the callback. If the user needs other arguments bind will help.
I opt for settling for global functions and static member functions, as it is a simple and flexible solution.
Thanks Rob, again your comments are gratefully received.
Vicente:
I don't know why I don't like the name paired_ptr, one_to_one_ptr could be an alternative.
How about bi_ptr? The object is then clearly a bidirectional pointer. one_to_one still seems ambiguous to me.
You are right one_to_one is no better. The class represents one of the ends of a bidirection association, mayb we have here the
Infact, is this library even a pointer? It never manages memory in any way. Except for the -> operator and the get() function (like smart_ptrs) it doesn't really have any responsibilities that a pointer has, the name is only intended to make clear that it isn't the object itself. But a pointer is usually a container for a single object, and this is not a container. Maybe it is a reference? But this would confuse the -> operator and the get() function...
I will see this class as one more in a Association library that could include other kind of associations, as one_to_many, many_to_one, many_to_many,...
While this immediately seems obvious, the one_to_one relationship is quite special. Here, both sides of the relationship share authority. A one to many or many to one relationship clearly has a single authoritative element - being the one rather than the many. How would these differ from a pointer container? And the many to many relationship is already dealt with in a way by the bimap library (as you later pointed out).
The one-to-one relationship is a pointer to pointer, while any relationship involving a 'many' starts to become a container and in any container, there must be an authoritative element to manage the contents. Would it be possible for a group of elements to manage the pool that they reside in? Is this really useful in any way?
To me, the one-to-one relationship is a special issue that can occur in the most simple of programs.
As no one side of the association is more important than the other maybe a non-member function could be more adequate. The connection between two objects can be established as so
connect(rex.paired_cat, kitty.paired_dog);
//connections can be severed at either end disconnect(kitty.paired_dog);
This is something I had already considered and have now wrapped paired_ptr.connect inside a global function as suggested, but have also left the paired_ptr.connect interface as a member also. I think both are useful, as the non-member function indicates the rationale of neither object being authoritative, while the connect member function indicates that either paired_ptr can initialize a connection.
I agree.
have you think about adding a mixin paired_ptr that can be used as base class and as such don't need to manage with the owner initialization?
I had considered this. I think that as a member, the object is more useful as it represents a 'has' relationship rather than a 'is' relationship - composition is primary to the rationale.
Nothing forbids to implement a has relationship using inheritance of a relation. Alexandrescu showed in its seminal book Modern C++ some techniques using inheritance to implement members.
Consider the following:
class person { paired_ptr<person,person> father; };
class person : public paired_ptr<person,person> { };
Obviously the inherited version poorly represents the concept of a father, as it suggests the person is a special type of a link between two people.
I have though to this already. The association can be tagged, as it does for example multi-index and bimap. struct father{}; class person : public paired_ptr<person,tagged<person,father>> { };
It also limits the class to only one paired_ptr, and of only one pair of types.
And allows to have more than one person class person : public paired_ptr<person, tagged<person,father>>, public paired_ptr<person, tagged<person,mother>> { };
However, it would fix the issue of initializing the owner of the paired_ptr member.
one_to_one_ptr<T,U> could define a method to get the pointed U, get<U>
A dynamic_cast version? I like that idea very much.
Not realy a dynamic_cast, just an overloading. Of course when tag are used, tags must be used. p.get<father>();
There is also Boost.Bimap
Thanks for reminding me. In a way, this library is a light weight version of bimap as it acts as a bimap holding two single values, mapping the type on the left to the type on the right. The advantage of paired_ptr is that there is no left and right, simply two ends of a link. paired_ptr is also a LOT simpler and hence much easier to use.
The left and right in bimap is only a way to name the two ends. It could be first and second also. The advantage of bimap is that it allows to iterate on the association and that the end classes are independent. I'm not saying yours is not useful. And yes, paired_ptr is much much simpler. I use a similar class to define roles a class can play. The difference is that a role needs always to be associated to an entity, so the association is created on role constructor and destroyed on role destruction or role migration. The entity objects allow to get the roles it plays and the role objects provide the same interface than the entity, including getting other roles of the entity.
Thanks again Vicente, I found your feedback very useful.
You are welcome.
Strasser:
reminds me of UML class diagram bi-directional associations.
Thanks for pointing this out. I think that kind of relationship is a common requirement when programming and is so often worked around in a c++ environment.
if this makes sense for C++ (I'm not sure) you also might want to consider other types of associations, e.g. n-ary associations that are automatically kept consistent on both ends of the association.
As Vicente mentioned, there is bimap that is a very complete bidirectional container library. I see the scope of this library as managing the one-to-one relationship. It is a pointer rather than a container, and as such, completes a very very different role. It has spawned from my thoughts on composition and the limitations of directional ownership.
I would say that your class can be seen as an *intrusive* way to implement a bidirectional association. paired_ptr implements the to-one end part of one-to-one. It would be great to have a class that implement the to-many end part of one-to-many and many-to-many. class person : public to_one<person, tagged<person, father>>, public to_one<person, tagged<person, mother>> public to_many<person, tagged<person, childrens>> { }; Best regards, ____________________ Vicente Juan Botet Escribá http://viboes.blogspot.com/

vicente.botet wrote:
From: "Dan Walters" <dan683@googlemail.com>
The problem is that to call a normal function, the arguments would be:
void callback_function(<paired_ptr<T,U>* p_ptr);
For a member function it would be:
void callback_function(T* this, <paired_ptr<T,U>* p_ptr);
Obviously, the this pointer is available in member functions and so is passed invisibly to the function. So the parameter lists are different and not inter-operable between global functions and member functions. This can be overcome using std::bind1st.
I think this is what Rob is saying. You need just to define the prototype for the callback. If the user needs other arguments bind will help.
Exactly.
I don't know why I don't like the name paired_ptr, one_to_one_ptr could be an alternative.
How about bi_ptr? The object is then clearly a bidirectional pointer. one_to_one still seems ambiguous to me.
You are right one_to_one is no better. The class represents one of the ends of a bidirection association, mayb we have here the
pairing_ptr? linking_ptr? connection? link? association? Some of those imply n-ary support, not just one-to-one, of course.
Infact, is this library even a pointer? It never manages memory in any way. Except for the -> operator and the get() function (like smart_ptrs) it doesn't really have any responsibilities that a pointer has, the name is only intended to make clear that it isn't the object itself. But a pointer is usually a container for a single object, and this is not a container. Maybe it is a reference? But this would confuse the -> operator and the get() function...
I think it is quite reasonable as a smart pointer. There are many uses for that class (no pun intended) of thing.
I will see this class as one more in a Association library that could include other kind of associations, as one_to_many, many_to_one, many_to_many,...
While this immediately seems obvious, the one_to_one relationship is quite special. Here, both sides of the relationship share authority. A one to many or many to one relationship clearly has a single authoritative element - being the one rather than the many. How would these differ from a pointer container? And the many to many relationship is already dealt with in a way by the bimap library (as you later pointed out).
Both arguments have merit. There are other approaches for one-to-many and many-to-many relationships. However, as you pointed out above, one of the distinguishing characteristics of your class is that it does no memory management. It also differs in that it provides callbacks to indicate when associations are formed and severed. Your class manages the associations and not the objects. Consequently, were that extended to one-to-many and many-to-many associations, it would remain distinct from other solutions.
The one-to-one relationship is a pointer to pointer, while any relationship involving a 'many' starts to become a container and in any container, there must be an authoritative element to manage the contents.
I disagree. It would be a container of pointers with callbacks as pointers are added and removed. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Dan Walters wrote:
Rob Stewart wrote:
That's an MSVC-specific warning. Use pragmas push, disable, and pop, conditionally compiled for MSVC, to manage that warning
For MSVC, warning 4355 is disabled in the paired_ptr header.
Did you use #pragma warning (push) and #pragma warning (pop) to control its scope?
Using Boost.Function makes your callback support more flexible, which makes it more useful to users.
Callback functions are now of type boost::function1<paired_ptr<T,U>*> where T is the owner type and U is the pointed to owner type. This
As I said before, do not assume that the object type for the member function pointer is the owner type. A user may wish to invoke a member function on a different object.
works well as users can generate global functions to handle the callbacks, use static member functions, and even static member functions from other classes. Hence for member usage:
class dog {public: static void connect_to_cat(paired_ptr<dog,cat>* p_paired_ptr) //
The argument type should be a reference since you'll ensure it is never null. Don't make the library user check that for every callback.
paired_cat.set_connect_callback(&dog::connect_to_cat);
No, it should be paired_cat.connect_callback(this, &dog::connect_to_cat); Notice that the object type and the member function type are supplied. The implementation of connect_callback() can create a boost::function, binding the this pointer, and then forward to the boost::function-based overload. That member function pointer overload isn't strictly necessary, but it is a nice convenience. That overload must be a member function template since the object pointer's type can differ from the owner type: template <class T, U> class paired_ptr { public: template <class V> void connect_callback(V *, void (V::*)(paired_ptr<T,U> &)); }; You should support this overload, too: template <class V> void connect_callback(V const *, void (V::*)(paired_ptr<T,U> &) const);
I fail to understand the problem. In each case you are invoking a functor with a reference to a paired_ptr. (You could even support overloading for const and non-const access.) What you need is type erasure to make the callback invocation ignorant of how the underlying function is invoked. IOW, you want a member function pointer invocation, via Boost.Function, say, to look just like calling a non-member function pointer or function object.
The problem is that to call a normal function, the arguments would be:
void callback_function(<paired_ptr<T,U>* p_ptr);
For a member function it would be:
void callback_function(T* this, <paired_ptr<T,U>* p_ptr);
Of course, but that's why I pointed out that you'd use type erasure via Boost.Function and Boost.Bind (or std::bind1st).
Obviously, the this pointer is available in member functions and so is passed invisibly to the function. So the parameter lists are different and not inter-operable between global functions and member functions. This can be overcome using std::bind1st.
Yep.
I opt for settling for global functions and static member functions, as it is a simple and flexible solution.
You don't need to leave out non-static member functions with the approach I suggested. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Hi, I want to comment some of the "Further Thoughts And Future Development" in the documentation. You said in the documentation Dan Walters-2 wrote:
1. Does this library belong within the smart_ptr library? In many ways it is similar in mechanics to the smart_ptrs but in a few ways it is fundamentally different, particularly in interface where an owner and callbacks are specified. Could this library be brought to conform more closely with the other smart_ptrs so that it can be included in this library? Or should paired_ptr have a new home?
I'm not sure this smart pointer should be included in the Boost.SmartPtr library. There are a lot of smart pointers to put all of them in Boost.SmartPtr. I would put it is a specific library. Intrusive Associations. Dan Walters-2 wrote:
2. Constructors and operators required. paired_ptrs need to be able to go in containers
to what constructors and operators are you referring to? Dan Walters-2 wrote:
3. the sizeof<paired_ptr> is 4 pointers, so 16 bytes assuming 4 bytes per pointer. Two of these pointers are the connect and disconnect callbacks. Should there be a separate callback version allowing an 8 byte skinny version without callbacks?
I agree that the callback version must be separated from the simpler one. Why do you need the owner? in which cases it is needed? Dan Walters-2 wrote:
4. should callbacks also provide a pointer to the specific paired_ptr that invoked the callback? This could be useful if an object contains a dynamic container of type paired_ptr.
No I don't thisnk so, as this is already stored on the pointer. Could you clarify your use case? Dan Walters-2 wrote:
5. polymorphic usage. You should be able to do paired_ptr<CDog, CAnimal> ptr_A; paired_ptr<CDog, CCat> ptr_B; ptr_A = ptr_B;
Yes this is a must have. Best, Vicente -- View this message in context: http://old.nabble.com/-paired-ptr--Proposing-a-new-smart-pointer-object-for-... Sent from the Boost - Dev mailing list archive at Nabble.com.

Vicente Botet Escriba wrote:
3. the sizeof<paired_ptr> is 4 pointers, so 16 bytes assuming 4 bytes per pointer. Two of these pointers are the connect and disconnect callbacks. Should there be a separate callback version allowing an 8 byte skinny version without callbacks?
I agree that the callback version must be separated from the simpler one. Why do you need the owner? in which cases it is needed? With the new callback prototype you don't need any more the owner. So if you make to independent classes, without call back only a pointer is needed. Best, Vicente. -- View this message in context: http://old.nabble.com/-paired-ptr--Proposing-a-new-smart-pointer-object-for-... Sent from the Boost - Dev mailing list archive at Nabble.com.

Hi all, Thank you Rob and Vicente again for your advice and encouragement. I will again try to respond to all at once. Vicente:
I think this is what Rob is saying. You need just to define the prototype for the callback. If the user needs other arguments bind will help.
What I have ended up doing is this: // connect_callback is a boost::function1<void,paired_ptr<T,U>*> template<class T1> void set_connect_callback(T1* p_object, void (T1::*member_function)(paired_ptr<T,U>*)) { connect_callback = std::bind1st(std::mem_fun(member_function), p_object); } There is also a non member version which assigns the non member function pointer directly to the boost::function1. So paired_ptr now supports: non member functions static member functions member functions // of any type
Nothing forbids to implement a has relationship using inheritance of a relation. Alexandrescu showed in its seminal book Modern C++ some techniques using inheritance to implement members.
Looking at your examples, I can see why this now makes sense. To implement this inherited version, it would need to be a separate class, and internally would need to work slightly differently. This is a less favorite implementation of mine as (while being much tidier to code with), it is harder to understand. The benefit of paired_ptr as a member, is that all programmers are familiar with the concept of a class member, and pointers. paired_ptr is used a little like a pointer. The limitations of the inherited version is that you can only have one paired_ptr to each set of types, and any user has to be more familiar with templates to be able to use the class. A member version can also be dynamically contained within containers, swapped with other objects, etc. Right now, despite your convincing argument, I am on the side of keeping it simple and easier to get to grips with, remaining with the non-inherited version. I could be convinced otherwise should there be enough support that the option is valuable.
Not realy a dynamic_cast, just an overloading. Of course when tag are used, tags must be used. p.get<father>();
I understand how this works now. Again, very very tidy interface. For me, the only drawback is that its going to need either more time with documentation or a more skilled user to get started with the library.
The left and right in bimap is only a way to name the two ends. It could be first and second also. The advantage of bimap is that it allows to iterate on the association and that the end classes are independent. I'm not saying yours is not useful. And yes, paired_ptr is much much simpler.
I use a similar class to define roles a class can play. The difference is that a role needs always to be associated to an entity, so the association is created on role constructor and destroyed on role destruction or role migration. The entity objects allow to get the roles it plays and the role objects provide the same interface than the entity, including getting other roles of the entity.
As opposed to your roles class, paired_ptr can be empty, as I understand. Should paired_ptr be a complete library, would it be able to solve the role-entity relationship sufficiently?
I'm not sure this smart pointer should be included in the Boost.SmartPtr library. There are a lot of smart pointers to put all of them in Boost.SmartPtr. I would put it is a specific library. Intrusive Associations.
Agreed, the library is a type of smart pointer, but its selling point is that it is an association.
to what constructors and operators are you referring to?
assignment, comparison, etc. I have barely started container support but they do not yet go in containers. I need to do more work before I can discuss this further really.
I agree that the callback version must be separated from the simpler one. Why do you need the owner? in which cases it is needed?
I need the owner as the relationship is as follows: T1 objectA <----> paired_ptr<T1,T2> <----> paired_ptr<T2,T1> <----> T2 objectB to be able to get objectB from objectA, you must trace along the complete line. Each object must be bidirectional to the following one. So, when objectA wants a pointer to objectB, it accesses its own paired_ptr, that retrieves the other paired_ptr, and gets the owner of that paired_ptr. A modification is that the local paired_ptr could contain the target object rather than the owner object. This would mean that connectiion rather than being paired_ptr<T,U>::connect(paired_ptr<U,T>*) you would now need paired_ptr<T,U>::connect(U*, paired_ptr<U,T>*) as every time you connect to a different target, you would need the pointer to that target object, but also the poointer to the paired_ptr object to manage that relationship. A more complex connect operation but no owner initialization function...... which to choose?
No I don't thisnk so, as this is already stored on the pointer. Could you clarify your use case?
If an object contains a std::container of type paired_ptr<person,person>, then the user is going to have a lot of paired_ptrs all calling back to the same callback functions. By providing the paired_ptr*, the function is now aware of which paired_ptr in the container has just connected / disconnected.
5. polymorphic usage. You should be able to do paired_ptr<CDog, CAnimal> ptr_A; paired_ptr<CDog, CCat> ptr_B; ptr_A = ptr_B;
Yes this is a must have.
This is supported. Note the following will not work. //class boy : public person paired_ptr<boy,person> paired1, paired2; paired1.connect(&paired2); // error: cannot convert paired_ptr<boy,person> to paired_ptr<person,boy> this tries to morph person into a boy. Instead you have to use: paired_ptr<person,person> paired1, paired2; Rob:
For MSVC, warning 4355 is disabled in the paired_ptr header.
Did you use #pragma warning (push) and #pragma warning (pop) to control its scope?
no, i just disabled. Note that the error is generated in the user defined class and not in the paired_ptr source.
As I said before, do not assume that the object type for the member function pointer is the owner type. A user may wish to invoke a member function on a different object.
callback now supports member functions from any class using a templated function.
The argument type should be a reference since you'll ensure it is never null. Don't make the library user check that for every callback.
You are absolutely right, I will go through the source and make sure I am using references in the correct places.
.... You should support this overload, too: ....
All solid points, I have now implemented. I am also using boost::bind rather than bind1st.
Of course, but that's why I pointed out that you'd use type erasure via Boost.Function and Boost.Bind (or std::bind1st).
This i somehow missed. Im on it now, and have made changes.
You don't need to leave out non-static member functions with the approach I suggested.
Did take me a while to get my head around how this works, but all sorted now.
pairing_ptr? linking_ptr? connection? link? association?
pairing is much better than paired as it suggests the operation rather than a state. I think ptr in the name is important as it helps the user understand quickly how the object may be used. connection and link do not really suggest the specifics. bidirectional_ptr or bi_ptr is probably the best name I can come up with at the moment. The object clearly is an association but that word doesn't really suggest the one to one relationship. As you say, suggesting n-ary support.
I think it is quite reasonable as a smart pointer. There are many uses for that class (no pun intended) of thing.
After further thought, I agree. This class is much closer to a pointer than anything else.
Both arguments have merit. There are other approaches for one-to-many and many-to-many relationships. However, as you pointed out above, one of the distinguishing characteristics of your class is that it does no memory management. It also differs in that it provides callbacks to indicate when associations are formed and severed. Your class manages the associations and not the objects. Consequently, were that extended to one-to-many and many-to-many associations, it would remain distinct from other solutions.
Very well argued. A one to many association could work where each paired_ptr connects to, rather than a single other paired_ptr, a container of objects. This container would provide callback functionality to all elements, and each element would be responsible for managing the container. Note with this design, the one to many relationship would have to be of a single type. The container can only hold a single type of object. This looses the powerful interface offered in paired_ptr where you can connect any type to any other type. With this considered, why would the one-to-many version be any different from any std::container<type*> ? Just the callback functionality allowing objects to share management of the association? Vicente:
With the new callback prototype you don't need any more the owner. So if you make to independent classes, without call back only a pointer is needed.
As i explain above, a paired_ptr must be aware of its owner so that the other paired_ptr can access its target object rather than just the paired_ptr member of that object. Vicente and Rob, thank you again for the great feedback and challenging conversation. I am currently working towards a new source release and updated / re-written documentation. In the mean time, please feel free to give any comments :D They are greatly appreciated. Best wishes, Dan

----- Original Message ----- From: "Dan Walters" <dan683@googlemail.com> To: <boost@lists.boost.org> Sent: Thursday, May 06, 2010 1:05 PM Subject: Re: [boost] [paired ptr] Proposing a new smart pointer object formanaging bidirectional relationships between objects
Vicente:
I think this is what Rob is saying. You need just to define the prototype for the callback. If the user needs other arguments bind will help.
What I have ended up doing is this:
// connect_callback is a boost::function1<void,paired_ptr<T,U>*> template<class T1> void set_connect_callback(T1* p_object, void (T1::*member_function)(paired_ptr<T,U>*)) { connect_callback = std::bind1st(std::mem_fun(member_function), p_object); }
There is also a non member version which assigns the non member function pointer directly to the boost::function1.
So paired_ptr now supports: non member functions static member functions member functions // of any type
Yes. This should work and some users will appreciate that you hide the use of bind, but this is not absolutely necesary.
Nothing forbids to implement a has relationship using inheritance of a relation. Alexandrescu showed in its seminal book Modern C++ some techniques using inheritance to implement members.
Looking at your examples, I can see why this now makes sense.
To implement this inherited version, it would need to be a separate class, and internally would need to work slightly differently.
This is a less favorite implementation of mine as (while being much tidier to code with), it is harder to understand. The benefit of paired_ptr as a member, is that all programmers are familiar with the concept of a class member, and pointers. paired_ptr is used a little like a pointer.
The limitations of the inherited version is that you can only have one paired_ptr to each set of types,
With the use of tagged types you can has as many as you want. tagged<person, child>, tagged<person, father>, ..;
and any user has to be more familiar with templates to be able to use the class. A member version can also be dynamically contained within containers, swapped with other objects, etc.
Right now, despite your convincing argument, I am on the side of keeping it simple and easier to get to grips with, remaining with the non-inherited version. I could be convinced otherwise should there be enough support that the option is valuable.
Not realy a dynamic_cast, just an overloading. Of course when tag are used, tags must be used. p.get<father>();
I understand how this works now. Again, very very tidy interface. For me, the only drawback is that its going to need either more time with documentation or a more skilled user to get started with the library.
The left and right in bimap is only a way to name the two ends. It could be first and second also. The advantage of bimap is that it allows to iterate on the association and that the end classes are independent. I'm not saying yours is not useful. And yes, paired_ptr is much much simpler.
I use a similar class to define roles a class can play. The difference is that a role needs always to be associated to an entity, so the association is created on role constructor and destroyed on role destruction or role migration. The entity objects allow to get the roles it plays and the role objects provide the same interface than the entity, including getting other roles of the entity.
As opposed to your roles class, paired_ptr can be empty, as I understand. Should paired_ptr be a complete library, would it be able to solve the role-entity relationship sufficiently?
I'm not sure this smart pointer should be included in the Boost.SmartPtr library. There are a lot of smart pointers to put all of them in Boost.SmartPtr. I would put it is a specific library. Intrusive Associations.
Agreed, the library is a type of smart pointer, but its selling point is that it is an association.
to what constructors and operators are you referring to?
assignment, comparison, etc. I have barely started container support but they do not yet go in containers. I need to do more work before I can discuss this further really.
I agree that the callback version must be separated from the simpler one. Why do you need the owner? in which cases it is needed?
I need the owner as the relationship is as follows:
T1 objectA <----> paired_ptr<T1,T2> <----> paired_ptr<T2,T1> <----> T2 objectB
to be able to get objectB from objectA, you must trace along the complete line. Each object must be bidirectional to the following one.
So, when objectA wants a pointer to objectB, it accesses its own paired_ptr, that retrieves the other paired_ptr, and gets the owner of that paired_ptr.
OK. I see the problem.
A modification is that the local paired_ptr could contain the target object rather than the owner object. This would mean that connectiion
rather than being
paired_ptr<T,U>::connect(paired_ptr<U,T>*)
you would now need
paired_ptr<T,U>::connect(U*, paired_ptr<U,T>*)
as every time you connect to a different target, you would need the pointer to that target object, but also the poointer to the paired_ptr object to manage that relationship.
A more complex connect operation but no owner initialization function...... which to choose?
I think that I have an idea. Currently when you connect the user does the following t->end1.connect(u->end2); It has all the informations. The idea is Suppose that paired_ptr<T, U> stores a pointer to U and that connect takes two tagged objects. template <typename TTag, typename UTag, typename T, typename U> void connect<father, child>(T*,U*); We can define a meta-function that giving a pointer to a class U and the tagged type tagged<Tag, T> retrieves the paired_ptr<U, tagged<T, Tag> >. template <typename T, typename Tag, typename U> struct get_paired_ptr //{ // static paired_ptr<U, tagged<T, Tag> >& apply(U*); //}; This metafunction must be specialized for each paired_ptr member. template <> struct get_paired_ptr<person, child, person> { static paired_ptr<person, tagged<person,child> >& apply(person* p) { return p->child_; } }; If you think that the user could find this hard to write you can provide a macro that do this. BOOST_PAIRED_PTR_GET_DCL(T, TAG, U, FIELD); BOOST_PAIRED_PTR_GET_DCL(child, person, person, child_); The function connect can be implemented as follows template <typename TTag, typename UTag, typename T, typename U> void connect<father, child>(T* t,U*u) { paired_ptr<T, tagged<U,UTag> > *ptrU = get_paired_ptr<T, tagged<U, UTag> >::apply(t); paired_ptr<U, tagged<T,TTag> > *ptrT = get_paired_ptr<U, tagged<T, TTag> >::apply(u); // as before // ... } The function get_paired_ptr can have as default behavior when the class T inherits from paired_ptr<T, tagged<U,UTag> >. If we are able to remove the owner, then the class doesn't need anymore two template classes. That is, paired_ptr will have only the pointee type. All the previous design will be a little bit more simple. I understand that you can find this too complex, but at the end the user needs to make not too many things, with the advantage that the paired_ptr takes only the size of a pointer. Another advangae is that this is more efficient as we have directly the poiner to the object avoinding a double indirection. I think that for the callbacks, it would be worth to try to have them statically. Maybe a system like the get_paired_ptr could work also. With the tags, we are doing some kind of reflexion, that allow us to get static information using metaprogramming, as the associated field and the callbacks.
No I don't thisnk so, as this is already stored on the pointer. Could you clarify your use case?
If an object contains a std::container of type paired_ptr<person,person>, then the user is going to have a lot of paired_ptrs all calling back to the same callback functions. By providing the paired_ptr*, the function is now aware of which paired_ptr in the container has just connected / disconnected.
5. polymorphic usage. You should be able to do paired_ptr<CDog, CAnimal> ptr_A; paired_ptr<CDog, CCat> ptr_B; ptr_A = ptr_B;
Yes this is a must have.
This is supported. Note the following will not work.
//class boy : public person
paired_ptr<boy,person> paired1, paired2; paired1.connect(&paired2); // error: cannot convert paired_ptr<boy,person> to paired_ptr<person,boy>
this tries to morph person into a boy.
Instead you have to use: paired_ptr<person,person> paired1, paired2;
I would use instead paired_ptr<boy,person> paired1; paired_ptr<person,boy> paired2; paired1.connect(&paired2); // this shoudl work Could you give an complete and concrete example needing polymorphysm that doesn works? Best, Vicente
participants (5)
-
Dan Walters
-
Stewart, Robert
-
strasser@uni-bremen.de
-
Vicente Botet Escriba
-
vicente.botet