
After experiencing some troubles with boost::python and enable_shared_from_this (as already reported in the past by someone to Peter Dimov), I started looking at the new (not documented) class enable_shared_from_this2. I made two changes in init_weak_once and now it seems to support shared_from_this in constructors and shared pointers "reinitialization". The original code (from boost 1.40): void init_weak_once() const { if( weak_this_._empty() ) { shared_this_.reset(static_cast< T* >( 0 ), detail::esft2_deleter_wrapper()); weak_this_ = shared_this_; } } The "patched" code: void init_weak_once() const { // Reinitialization support if( weak_this_.expired() ) { // shared_from_this in costructors support shared_this_.reset(static_cast <T*>(const_cast<enable_shared_from_this2>(this)), detail::esft2_deleter_wrapper()); weak_this_ = shared_this_; } } I know that the static_cast/const_cast is "problematic" on VC6 (and maybe other compilers) but it could be solved using an offset from enable_shared_from_this2 * to T *. I've attached a testcase that shows the problems with the current enable_shared_from_this2 implementation (with the proposed patch it works). Any feedback about this? struct null_deleter { template <typename T> inline void operator()(T *p) const { } }; class EnableThisPtrTester : public boost::enable_shared_from_this2<EnableThisPtrTester> { public: EnableThisPtrTester() { } EnableThisPtrTester(shared_ptr<EnableThisPtrTester> &ptr) { ptr = shared_from_this(); BOOST_CHECK(ptr); } }; BOOST_AUTO_TEST_CASE(test_enable_this_ptr) { { shared_ptr<EnableThisPtrTester> ptr1; shared_ptr<EnableThisPtrTester> ptr2(new EnableThisPtrTester(ptr1)); BOOST_CHECK(ptr1 == ptr2); BOOST_CHECK(ptr1.use_count() == ptr2.use_count()); BOOST_CHECK(ptr1->shared_from_this() == ptr1); BOOST_CHECK(ptr1->shared_from_this().use_count() == ptr1.use_count()); shared_ptr<EnableThisPtrTester> ptr3 = ptr2->shared_from_this(); BOOST_CHECK(ptr2 == ptr3); BOOST_CHECK(ptr2.use_count() == ptr3.use_count()); BOOST_CHECK(ptr1->shared_from_this().use_count() == ptr1.use_count()); } { shared_ptr<EnableThisPtrTester> ptr1; EnableThisPtrTester tester(ptr1); shared_ptr<EnableThisPtrTester> ptr2 = tester.shared_from_this(); BOOST_CHECK(ptr1 == ptr2); BOOST_CHECK(ptr1.use_count() == ptr2.use_count()); ptr1.reset(); ptr2.reset(); } { EnableThisPtrTester tester; { shared_ptr<EnableThisPtrTester> ptr1 = tester.shared_from_this(); shared_ptr<EnableThisPtrTester> ptr2 = tester.shared_from_this(); BOOST_CHECK(ptr1 == ptr2); BOOST_CHECK(ptr1.use_count() == ptr2.use_count()); shared_ptr<EnableThisPtrTester> ptr3(&tester, null_deleter()); BOOST_CHECK(ptr1 == ptr3); BOOST_CHECK(ptr1.use_count() == ptr3.use_count()); shared_ptr<EnableThisPtrTester> ptr4 = tester.shared_from_this(); BOOST_CHECK(ptr4 == ptr1); BOOST_CHECK(ptr4 == ptr3); BOOST_CHECK(ptr1.use_count() == ptr4.use_count()); BOOST_CHECK(ptr3.use_count() == ptr4.use_count()); } BOOST_CHECK(tester.shared_from_this()); } }

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Monday 26 October 2009, Berserker wrote:
The "patched" code:
void init_weak_once() const { // Reinitialization support if( weak_this_.expired() ) { // shared_from_this in costructors support shared_this_.reset(static_cast <T*>(const_cast<enable_shared_from_this2>(this)), detail::esft2_deleter_wrapper()); weak_this_ = shared_this_; } }
I know that the static_cast/const_cast is "problematic" on VC6 (and maybe other compilers) but it could be solved using an offset from enable_shared_from_this2 * to T *. I've attached a testcase that shows the problems with the current enable_shared_from_this2 implementation (with the proposed patch it works). Any feedback about this?
IIRC, the original version of enable_shared_from_this that supported use in constructors did a static_cast to the derived type. But it failed some of the tests, so it was changed to a dynamic_cast. The version currently in svn looks broken, like it was from a later version which relied on a shared_from_this() free function like: template<typename T> shared_ptr<T> shared_from_this(T *); which used shared_ptr aliasing to create and return a shared_ptr which pointed at the same object as was passed in as an argument (so enable_shared_from_this didn't have to do a cast or store a pointer to the derived type). But I don't see any such free function in enable_shared_from_this2.hpp. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkrnL7QACgkQ5vihyNWuA4XFAACfZR2MYD0G5yVKwykKTq+BGwU1 Zm8An0ChaK+AZX/Pp3CRVKzWJKRS2JjL =Qxri -----END PGP SIGNATURE-----

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Tuesday 27 October 2009, Peter Dimov wrote:
Frank Mori Hess wrote:
The version currently in svn looks broken, ...
It passes esft_constructor_test, which you wrote. :-)
I can fix that :) It looks like I only did tests of ownership, I never tested the actual pointer value that was returned. I think I can fix enable_shared_from_this2.hpp tommorrow, would it be okay for me to commit changes to it to trunk? I'd like to go the path of a non-template enable_shared_from_this2 with a free shared_from_this() function. The other option would be adding a vtable to enable_shared_from_this2 and using dynamic_cast (which I think I'm now remembering was required to make the virtual inheritance stuff in shared_from_this_test.cpp pass). -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkrnTWoACgkQ5vihyNWuA4XwrwCeOJXvd5onLA1yUZICgkgvj/8z QLYAoNzbrowruGFlcmnTgfOL/4AWSQZp =r36I -----END PGP SIGNATURE-----

Frank Mori Hess wrote:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On Tuesday 27 October 2009, Peter Dimov wrote:
Frank Mori Hess wrote:
The version currently in svn looks broken, ...
It passes esft_constructor_test, which you wrote. :-)
I can fix that :) It looks like I only did tests of ownership, I never tested the actual pointer value that was returned. I think I can fix enable_shared_from_this2.hpp tommorrow, would it be okay for me to commit changes to it to trunk?
Before fixing it, can you please show me a test case that fails? shared_from_this_test.cpp also seems to work when switched to esft2 (a test that I should have added, but didn't, for some reason). Do you see anything wrong? The missing #include <boost/weak_ptr.hpp> doesn't count. ;-) FWIW, I do not object in principle if you decide to
go the path of a non-template enable_shared_from_this2 with a free shared_from_this() function;
it's just that the current esft2 was supposed to be a faithful reconstruction of your constructor-enabled esft (minus the get_deleter special case to keep shared_ptr unaware of it).

Peter Dimov wrote:
Before fixing it, can you please show me a test case that fails?
I get it. I haven't read Berserker's tests carefully (sorry), and our tests do indeed not cover this case. Either ~enable_shared_from_this2 should be made virtual and (T*)0 be made a dynamic_cast<T*>(this) as in the original, or shared_from_this should be a free function, as you suggest. (How about 'shared_from_raw' as a name for the free function?)

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Tuesday 27 October 2009, Peter Dimov wrote:
(How about 'shared_from_raw' as a name for the free function?)
That's fine by me. I also like shared_from_pop (pop == plain old pointer) although that might be more obscure. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkrnjngACgkQ5vihyNWuA4UJ1wCg6J7pWMLOCrwlkbzaR+P+pQWX LRgAoNeX+dDtgUxzZylXakxqbtvyW9jq =lW5c -----END PGP SIGNATURE-----

Frank Mori Hess wrote:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On Tuesday 27 October 2009, Peter Dimov wrote:
(How about 'shared_from_raw' as a name for the free function?)
That's fine by me. I also like shared_from_pop (pop == plain old pointer) although that might be more obscure.
OK, to get back to your earlier question, I consider you the 'owner' of enable_shared_from_this2, so feel free to fix it whichever way you want. :-)

On Tue, Oct 27, 2009 at 8:42 PM, Peter Dimov <pdimov@pdimov.com> wrote:
Frank Mori Hess wrote:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On Tuesday 27 October 2009, Peter Dimov wrote:
(How about 'shared_from_raw' as a name for the free function?)
That's fine by me. I also like shared_from_pop (pop == plain old pointer) although that might be more obscure.
OK, to get back to your earlier question, I consider you the 'owner' of enable_shared_from_this2, so feel free to fix it whichever way you want. :-)
Fix it "whatever way you want" :-), but call it _raw, not _pop -- as a user, I'd only understand the first one. Tony

On Tuesday 27 October 2009, Peter Dimov wrote:
OK, to get back to your earlier question, I consider you the 'owner' of enable_shared_from_this2, so feel free to fix it whichever way you want. :-)
I've commited boost/smart_ptr/enabled_shared_from_raw.hpp to trunk (I svn moved enable_shared_from_this2.hpp). It provides a (non-template) boost::enabled_shared_from_raw base class, and a free function template boost::shared_from_raw(). It supports usage from constructors and re-initialization after shared_ptr expiration. I'll try to add a html page for it to the documentation this weekend.

Frank Mori Hess wrote:
I've commited boost/smart_ptr/enabled_shared_from_raw.hpp to trunk (I svn moved enable_shared_from_this2.hpp).
So long as we're innovating, consider adding weak_from_raw as well. It can give you an expired weak_ptr to 'this' from within a destructor, which is useful for deregistration.

On Wed, Oct 28, 2009 at 6:45 PM, Peter Dimov <pdimov@pdimov.com> wrote:
Frank Mori Hess wrote:
I've commited boost/smart_ptr/enabled_shared_from_raw.hpp to trunk (I svn moved enable_shared_from_this2.hpp).
So long as we're innovating, consider adding weak_from_raw as well. It can give you an expired weak_ptr to 'this' from within a destructor, which is useful for deregistration.
Or you can use a factory function for registration and a deleter for deregistration. That way the object registry is not coupled with T. Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

On Wednesday 28 October 2009, Peter Dimov wrote:
Frank Mori Hess wrote:
I've commited boost/smart_ptr/enabled_shared_from_raw.hpp to trunk (I svn moved enable_shared_from_this2.hpp).
So long as we're innovating, consider adding weak_from_raw as well. It can give you an expired weak_ptr to 'this' from within a destructor, which is useful for deregistration.
I think that would require an aliasing constructor for weak_ptr, or friend access to weak_ptr. Perhaps a modification of weak_ptr::_internal_assign(), which no longer seems to be used?

Frank Mori Hess wrote:
So long as we're innovating, consider adding weak_from_raw as well. It can give you an expired weak_ptr to 'this' from within a destructor, which is useful for deregistration.
I think that would require an aliasing constructor for weak_ptr, or friend access to weak_ptr.
Yes, you're right, I was thinking in terms of the old and busted enable_shared_from_this.
Perhaps a modification of weak_ptr::_internal_assign(), which no longer seems to be used?
Feel free to remove its second argument. :-)

I get it. I haven't read Berserker's tests carefully (sorry), and our tests do indeed not cover this case. Either ~enable_shared_from_this2 should be made virtual and (T*)0 be made a dynamic_cast<T*>(this) as in the original, or shared_from_this should be a free function, as you suggest. (How about 'shared_from_raw' as a name for the free function?)
Thanks for yours replies, I hope that you'll find the time to have a look at my test :) Peter did you remember the problem related to boost::python I'm talking about? Here is the link of your reply http://lists.boost.org/boost-users/2008/08/38864.php I'm experiencing that problem and the only way I can solve it is using the patch in my first message. I'll "suggest" two new methods in enable_shared_from_this2 too: template <typename I> inline shared_ptr<I> shared_from_this() { return boost::dynamic_pointer_cast<I>(shared_from_this()); } template <typename I> inline shared_ptr<I const> shared_from_this() const { return boost::dynamic_pointer_cast<I const>(shared_from_this()); } This is for sure nothing special, but I think it's very useful in case of overriding from base classes which inherit from enable_shared_from_this2, for example: class A : public enable_shared_from_this2<A> { }; class B : public A { void foo1() { // short version :) shared_ptr<B> me = shared_from_this<B>(); } void foo2() { // verbose version :( shared_ptr<B> me = boost::dynamic_pointer_cast<B>(shared_from_this()); } };

Berserker wrote:
Thanks for yours replies, I hope that you'll find the time to have a look at my test :) Peter did you remember the problem related to boost::python I'm talking about? Here is the link of your reply http://lists.boost.org/boost-users/2008/08/38864.php
I remember now. But I thought I had fixed it. In this message I say:
We've been thinking of changing the behavior of enable_shared_from_this in such cases, making it ignore subsequent shared_ptr instances to the same object and having it stick to the first one. This, however, will not happen for the upcoming 1.36 release of Boost.
You can in principle achieve the same result by patching your local copy of Boost to make weak_ptr::_internal_assign only initialize when this->expired() is true, but this has never been tested.
and, in fact, the code in the trunk and in the release branch already does this: // Note: invoked automatically by shared_ptr; do not call template<class X, class Y> void _internal_accept_owner( shared_ptr<X> const * ppx, Y * py ) const { if( weak_this_.expired() ) { weak_this_ = shared_ptr<T>( *ppx, py ); } } There is even a test for that, esft_second_ptr_test.cpp: boost::shared_ptr<X> px( new X ); { boost::shared_ptr<X> px2( px.get(), null_deleter ); BOOST_TEST( px == px2 ); } try { boost::shared_ptr< X > qx = px->shared_from_this(); BOOST_TEST( px == qx ); BOOST_TEST( !( px < qx ) && !( qx < px ) ); } catch( boost::bad_weak_ptr const& ) { BOOST_ERROR( "px->shared_from_this() failed" ); }

I remember now. But I thought I had fixed it. In this message I say: and, in fact, the code in the trunk and in the release branch already does this:
That's right but please have a look at my test example. You can comment out the constructor stuffs and try to switch from enable_shared_from_this and enable_shared_from_this2: there are other cases where it fails (shared_ptrs reinitialization in particular).

Berserker wrote:
I remember now. But I thought I had fixed it. In this message I say: and, in fact, the code in the trunk and in the release branch already does this:
That's right but please have a look at my test example. You can comment out the constructor stuffs and try to switch from enable_shared_from_this and enable_shared_from_this2: there are other cases where it fails (shared_ptrs reinitialization in particular).
All of your tests rely on the constructor stuff... if by reinitialization you mean something like #include <boost/enable_shared_from_this.hpp> #include <boost/shared_ptr.hpp> #include <boost/detail/lightweight_test.hpp> // class X: public boost::enable_shared_from_this<X> { }; void null_deleter( void const* ) { } void test( X & x ) { boost::shared_ptr<X> px( &x, null_deleter ); try { boost::shared_ptr< X > qx = px->shared_from_this(); BOOST_TEST( px == qx ); BOOST_TEST( !( px < qx ) && !( qx < px ) ); } catch( boost::bad_weak_ptr const& ) { BOOST_ERROR( "px->shared_from_this() failed" ); } } int main() { X x; test( x ); test( x ); return boost::report_errors(); } then it passes.

The expirity check seems working fine to me if merged in enable_shared_ptr2 and solves some problems. I can summarize other boost::python's problems in this example: class X : public boost::enable_shared_from_this2<X> { public: void test() { shared_ptr<X> me = shared_from_this(); BOOST_ASSERT(me); } }; void expose_x() { boost::python::class_<X>("X", boost::python::init<>()). def("test", &X::test); } ------------------------------------ C++ case 1 (works fine): shared_ptr<X> x(new X); x->test(); ------------------------------------ C++ case 2 (doesn't work because of the missing static/dynamic cast): X x; x.test(); ------------------------------------ Python case (doesn't work, same problem of C++ case 2) x = X() x.test()

News about this problem? I just checked the latest svn revision and it seems that the code below doesn't work yet. Berserker wrote:
The expirity check seems working fine to me if merged in enable_shared_ptr2 and solves some problems. I can summarize other boost::python's problems in this example:
class X : public boost::enable_shared_from_this2<X> { public: void test() { shared_ptr<X> me = shared_from_this(); BOOST_ASSERT(me); } };
void expose_x() { boost::python::class_<X>("X", boost::python::init<>()). def("test", &X::test); }
------------------------------------
C++ case 1 (works fine):
shared_ptr<X> x(new X); x->test();
------------------------------------
C++ case 2 (doesn't work because of the missing static/dynamic cast):
X x; x.test();
------------------------------------
Python case (doesn't work, same problem of C++ case 2)
x = X() x.test()
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

I would also like to express my interest in a solution to the enable_shared_from_this/python problem. In my opinion providing an adequate solution would really benefit boost::python and I'm glad to see work is being done. I've checked out the latest code from svn and played around with it. I had to modify enable_shared_from_raw.hpp slightly in order to get it to compile (mainly insert esft2_deleter_wrapper from the old enable_shared_from_this2.hpp). Once it compiled I tested it in the following scenario: #include <iostream> #include <string> #define BOOST_ALL_DYN_LINK 1 #include <boost/smart_ptr/enable_shared_from_raw.hpp> #include <boost/make_shared.hpp> #include <boost/smart_ptr.hpp> #include <boost/python.hpp> namespace py = boost::python; class Object: public boost::enable_shared_from_raw //public boost::enable_shared_from_this<Object> { public: Object(const std::string& _name): name(_name) { std::cout << "Construct: " << name << std::endl; } ~Object() { std::cout << "Destruct: " << name << std::endl; } boost::shared_ptr<Object> shared() { boost::shared_ptr<Object> self = boost::shared_from_raw<Object>(this); //shared_from_this(); BOOST_ASSERT(self); return self; } public: std::string name; }; BOOST_PYTHON_MODULE(module) { { //::Object typedef py::class_< Object > exposer_t; exposer_t exposer = exposer_t("Object", py::init<const std::string&>()); exposer.def_readwrite("name",&Object::name); exposer.def("shared",&Object::shared); py::register_ptr_to_python< boost::shared_ptr< Object > >(); } } int main(int argc, char *argv[]) { int exit = EXIT_SUCCESS; Py_Initialize(); try { initmodule(); py::object main_module = py::import("__main__"); py::object main_namespace = main_module.attr("__dict__"); main_namespace["obj1"] = boost::make_shared<Object>("C++"); py::exec( "import module\n" "print obj1.shared().name\n" "obj2 = module.Object('Python')\n" "print obj2.shared().name\n", // RuntimeError: tr1::bad_weak_ptr main_namespace, main_namespace ); } catch(const py::error_already_set&) { PyErr_Print(); exit = EXIT_FAILURE; } Py_Finalize(); return exit; } The results look good: the RuntimeError is gone, the objects are being destroyed. Unfortunately, I only know little about the inner workings smart pointers and even less about boost::python, so the before mentioned code should be regarded with caution. So far, I've discovered one case where this breaks, i.e. the following python code "obj2 = obj2.shared()" causes the assertion in the destructor of enable_shared_from_raw to fail. I'll assume that this is work in progress (or really difficult to solve). Anyways, keep up the good work! Berserker wrote:
News about this problem? I just checked the latest svn revision and it seems that the code below doesn't work yet.
Berserker wrote:
The expirity check seems working fine to me if merged in enable_shared_ptr2 and solves some problems. I can summarize other boost::python's problems in this example:
class X : public boost::enable_shared_from_this2<X> { public: void test() { shared_ptr<X> me = shared_from_this(); BOOST_ASSERT(me); } };
void expose_x() { boost::python::class_<X>("X", boost::python::init<>()). def("test", &X::test); }
------------------------------------
C++ case 1 (works fine):
shared_ptr<X> x(new X); x->test();
------------------------------------
C++ case 2 (doesn't work because of the missing static/dynamic cast):
X x; x.test();
------------------------------------
Python case (doesn't work, same problem of C++ case 2)
x = X() x.test()
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Sunday 07 March 2010, Daniel F. wrote:
I would also like to express my interest in a solution to the enable_shared_from_this/python problem. In my opinion providing an adequate solution would really benefit boost::python and I'm glad to see work is being done. I've checked out the latest code from svn and played around with it. I had to modify enable_shared_from_raw.hpp slightly in order to get it to compile (mainly insert esft2_deleter_wrapper from the old enable_shared_from_this2.hpp).
What errors did you see? Can you provide a test program which shows the errors? The trunk works fine for me. esft2_deleter_wrapper is defined in shared_ptr.hpp right above get_deleter.
The results look good: the RuntimeError is gone, the objects are being destroyed. Unfortunately, I only know little about the inner workings smart pointers and even less about boost::python, so the before mentioned code should be regarded with caution. So far, I've discovered one case where this breaks, i.e. the following python code "obj2 = obj2.shared()" causes the assertion in the destructor of enable_shared_from_raw to fail. I'll assume that this is work in progress (or really difficult to solve).
I don't know anything about Boost.Python, but the assertion will fail if you create a shared_ptr with shared_from_raw() and then the object is destroyed before ever being given to an external shared_ptr. It's fine if the external shared_ptr has a null deleter, but you have to construct such a shared_ptr explicitly if that's what you want. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkuWdy8ACgkQ5vihyNWuA4WkpgCggqvLM1ImFLmyYA+R7GqT+PDe L/MAoIA5IRf9vpV/39inCU5GJZ2+Yy0M =stxS -----END PGP SIGNATURE-----

You are right, I had my include paths jumbled up (it was including headers from an older version of boost) - sorry about that. Also, thanks for providing some insight on why the assertion fails. The object being deleted before the name is bound (resulting in the assignment to the external shared_ptr) sounds like a reasonable explanation. The code was a bit of a contrived example anyways - and it is easy to fix: temp = obj2.shared() obj2 = temp However, it does mean that as long as this issue exists, extra caution is necessary. This behavior could be surprising to some users, especially those coming from python. Frank Mori Hess wrote:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On Sunday 07 March 2010, Daniel F. wrote:
I would also like to express my interest in a solution to the enable_shared_from_this/python problem. In my opinion providing an adequate solution would really benefit boost::python and I'm glad to see work is being done. I've checked out the latest code from svn and played around with it. I had to modify enable_shared_from_raw.hpp slightly in order to get it to compile (mainly insert esft2_deleter_wrapper from the old enable_shared_from_this2.hpp).
What errors did you see? Can you provide a test program which shows the errors? The trunk works fine for me. esft2_deleter_wrapper is defined in shared_ptr.hpp right above get_deleter.
The results look good: the RuntimeError is gone, the objects are being destroyed. Unfortunately, I only know little about the inner workings smart pointers and even less about boost::python, so the before mentioned code should be regarded with caution. So far, I've discovered one case where this breaks, i.e. the following python code "obj2 = obj2.shared()" causes the assertion in the destructor of enable_shared_from_raw to fail. I'll assume that this is work in progress (or really difficult to solve).
I don't know anything about Boost.Python, but the assertion will fail if you create a shared_ptr with shared_from_raw() and then the object is destroyed before ever being given to an external shared_ptr. It's fine if the external shared_ptr has a null deleter, but you have to construct such a shared_ptr explicitly if that's what you want. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux)
iEYEARECAAYFAkuWdy8ACgkQ5vihyNWuA4WkpgCggqvLM1ImFLmyYA+R7GqT+PDe L/MAoIA5IRf9vpV/39inCU5GJZ2+Yy0M =stxS -----END PGP SIGNATURE----- _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
participants (7)
-
Berserker
-
Daniel F.
-
Emil Dotchevski
-
Frank Mori Hess
-
Frank Mori Hess
-
Gottlob Frege
-
Peter Dimov