[congif] BOOST_BEFRIEND_TEMPLATE, BOOST_PRIVATE

Hi, <boost/shared_ptr.hpp> contains the following in the public section of the class definition (reformatted): // Tasteless as this may seem, making all members public // allows member templates to work in the absence of member // template friends. (Matthew Langston) #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS private: template<class Y> friend class shared_ptr; template<class Y> friend class weak_ptr; #endif T * px; // contained pointer detail::shared_count pn; // reference counter This has become a pretty common technique, I believe. I certainly use it a lot, at any rate. I'd like to suggest two macros which would allow code like the above to be simplified as follows: BOOST_PRIVATE: BOOST_BEFRIEND_TEMPLATE(shared_ptr, Y, 1) BOOST_BEFRIEND_TEMPLATE(weak_ptr, Y, 1) T * px; // contained pointer detail::shared_count pn; // reference counter Here BOOST_PRIVATE would expand to "private" for compilers that support template friends and to "public" otherwise; BOOST_BEFRIEND_TEMPLATE would expand to a template friend declaration where supported, and to nothing otherwise. It might be desirable to have two macros BOOST_BEFRIEND_TEMPLATE_CLASS and BOOST_BEFRIEND_TEMPLATE_STRUCT to avoid compiler warnings. Jonathan

Jonathan Turkanis wrote:
Hi,
<boost/shared_ptr.hpp> contains the following in the public section of the class definition (reformatted):
// Tasteless as this may seem, making all members public // allows member templates to work in the absence of member // template friends. (Matthew Langston)
#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
private:
template<class Y> friend class shared_ptr; template<class Y> friend class weak_ptr;
#endif
T * px; // contained pointer detail::shared_count pn; // reference counter
This has become a pretty common technique, I believe. I certainly use it a lot, at any rate.
I'd like to suggest two macros which would allow code like the above to be simplified as follows:
BOOST_PRIVATE: BOOST_BEFRIEND_TEMPLATE(shared_ptr, Y, 1) BOOST_BEFRIEND_TEMPLATE(weak_ptr, Y, 1)
T * px; // contained pointer detail::shared_count pn; // reference counter
This doesn't look any better to me than the original, sorry. ;-)

"Peter Dimov" <pdimov@mmltd.net> writes:
BOOST_BEFRIEND_TEMPLATE(shared_ptr, Y, 1) BOOST_BEFRIEND_TEMPLATE(weak_ptr, Y, 1) T * px; // contained pointer detail::shared_count pn; // reference counter
This doesn't look any better to me than the original, sorry. ;-)
I agree with Peter. In fact, to me it looks significantly worse. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
"Peter Dimov" <pdimov@mmltd.net> writes:
BOOST_BEFRIEND_TEMPLATE(shared_ptr, Y, 1) BOOST_BEFRIEND_TEMPLATE(weak_ptr, Y, 1) T * px; // contained pointer detail::shared_count pn; // reference counter
This doesn't look any better to me than the original, sorry. ;-)
I agree with Peter. In fact, to me it looks significantly worse.
Well, there's no accounting for taste. ;-) I use similar macros a lot in the Preboost Interfaces library. Jonathan

Jonathan Turkanis wrote:
David Abrahams wrote:
"Peter Dimov" <pdimov@mmltd.net> writes:
BOOST_BEFRIEND_TEMPLATE(shared_ptr, Y, 1) BOOST_BEFRIEND_TEMPLATE(weak_ptr, Y, 1) T * px; // contained pointer detail::shared_count pn; // reference counter
This doesn't look any better to me than the original, sorry. ;-)
I agree with Peter. In fact, to me it looks significantly worse.
Well, there's no accounting for taste. ;-) I use similar macros a lot in the Preboost Interfaces library.
This has nothing to do with taste. The original version of the code can be understood immediately as it only relies on general C++ knowledge. The macro-based version adds a level of indirection; you now need to look at the documentation or the definition of the macros.

Peter Dimov wrote:
Jonathan Turkanis wrote:
David Abrahams wrote:
"Peter Dimov" <pdimov@mmltd.net> writes:
BOOST_BEFRIEND_TEMPLATE(shared_ptr, Y, 1) BOOST_BEFRIEND_TEMPLATE(weak_ptr, Y, 1) T * px; // contained pointer detail::shared_count pn; // reference counter
This doesn't look any better to me than the original, sorry. ;-)
I agree with Peter. In fact, to me it looks significantly worse.
Well, there's no accounting for taste. ;-) I use similar macros a lot in the Preboost Interfaces library.
This has nothing to do with taste. The original version of the code can be understood immediately as it only relies on general C++ knowledge. The macro-based version adds a level of indirection; you now need to look at the documentation or the definition of the macros.
To me the meaning is immediately obvious. If it's not immediately obvious to nearly everyone, then it's not a suitable config macro; by this standard, and judging by the comments the suggestion has received, it's unsuitable. Nobody likes macros with obscure names which require the reader to consult the documentation. Jonathan

"Peter Dimov" <pdimov@mmltd.net> writes:
Jonathan Turkanis wrote:
David Abrahams wrote:
"Peter Dimov" <pdimov@mmltd.net> writes:
BOOST_BEFRIEND_TEMPLATE(shared_ptr, Y, 1) BOOST_BEFRIEND_TEMPLATE(weak_ptr, Y, 1) T * px; // contained pointer detail::shared_count pn; // reference counter
This doesn't look any better to me than the original, sorry. ;-)
I agree with Peter. In fact, to me it looks significantly worse.
Well, there's no accounting for taste. ;-) I use similar macros a lot in the Preboost Interfaces library.
This has nothing to do with taste. The original version of the code can be understood immediately as it only relies on general C++ knowledge. The macro-based version adds a level of indirection; you now need to look at the documentation or the definition of the macros.
Right. It would be different if the macros significantly raised the abstraction level, but they don't. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
"Peter Dimov" <pdimov@mmltd.net> writes:
Jonathan Turkanis wrote:
David Abrahams wrote:
"Peter Dimov" <pdimov@mmltd.net> writes:
BOOST_BEFRIEND_TEMPLATE(shared_ptr, Y, 1) BOOST_BEFRIEND_TEMPLATE(weak_ptr, Y, 1) T * px; // contained pointer detail::shared_count pn; // reference counter
This doesn't look any better to me than the original, sorry. ;-)
I agree with Peter. In fact, to me it looks significantly worse.
Well, there's no accounting for taste. ;-) I use similar macros a lot in the Preboost Interfaces library.
This has nothing to do with taste. The original version of the code can be understood immediately as it only relies on general C++ knowledge. The macro-based version adds a level of indirection; you now need to look at the documentation or the definition of the macros.
Right. It would be different if the macros significantly raised the abstraction level, but they don't.
The reason I like the macros is that you only need one version of the code, and -- if you find the macro names intuitive -- the version with the macros reads like the version for conforming compilers. It's basically the same idea as BOOST_USE_FACET. Jonathan

"Jonathan Turkanis" <technews@kangaroologic.com> writes:
David Abrahams wrote:
"Peter Dimov" <pdimov@mmltd.net> writes:
Jonathan Turkanis wrote:
David Abrahams wrote:
"Peter Dimov" <pdimov@mmltd.net> writes:
> BOOST_BEFRIEND_TEMPLATE(shared_ptr, Y, 1) > BOOST_BEFRIEND_TEMPLATE(weak_ptr, Y, 1) > T * px; // contained pointer > detail::shared_count pn; // reference counter
This doesn't look any better to me than the original, sorry. ;-)
I agree with Peter. In fact, to me it looks significantly worse.
Well, there's no accounting for taste. ;-) I use similar macros a lot in the Preboost Interfaces library.
This has nothing to do with taste. The original version of the code can be understood immediately as it only relies on general C++ knowledge. The macro-based version adds a level of indirection; you now need to look at the documentation or the definition of the macros.
Right. It would be different if the macros significantly raised the abstraction level, but they don't.
The reason I like the macros is that you only need one version of the code,
I consider the #ifdef idiom to be only "one version of the code", when I look at it. I generally don't need protected members, so I put the friends right between the public and private stuff, where it belongs: class fu { public: . . . #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS private: // template friends template<class Y> friend class shared_ptr; template<class Y> friend class weak_ptr; #endif private: // data members T* px; detail::shared_count pn; }; Clean and quiet.
and -- if you find the macro names intuitive -- the version with the macros reads like the version for conforming compilers.
Just wait till you start needing nontype template parameters.
It's basically the same idea as BOOST_USE_FACET.
Never had to use that one. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
"Jonathan Turkanis" writes:
The reason I like the macros is that you only need one version of the code,
I consider the #ifdef idiom to be only "one version of the code", when I look at it. I generally don't need protected members, so I put the friends right between the public and private stuff, where it belongs:
class fu { public: . . . #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS private: // template friends template<class Y> friend class shared_ptr; template<class Y> friend class weak_ptr; #endif
private: // data members T* px; detail::shared_count pn; };
Clean and quiet.
I didn't realize macros were noisy. Looking at the interfaces library, which uses the macros extensively, I see that the main use comes in base class lists class derived : BOOST_IDL_PRIVATE base and in macros, which can't contain preprocessor directives. Maybe this device is less useful in non-macro-based libraries.
Just wait till you start needing nontype template parameters.
I didn't say it was a panacea.
It's basically the same idea as BOOST_USE_FACET.
Never had to use that one.
or BOOST_STATIC_CONSTANT. Jonathan
participants (3)
-
David Abrahams
-
Jonathan Turkanis
-
Peter Dimov