boost::none for boost::shared_ptr
Hello, Does boost::shared_ptr offer a way to create an empty shared pointer without a lot of typing? Perhaps something analogous to boost::none. I am not using c++11. Thank you, Chris == using boost::none; using boost::optional; // declare f(optional<CSomeReallyLongClassName> Item); g(shared_ptr<CSomeReallyLongClassName> pItem); // invoke f with empty object f(none); // invoke g with empty object g(shared_ptr<CSomeReallyLongClassName>());
On 30/01/14 01:27, Chris Stankevitz wrote:
Hello,
Does boost::shared_ptr offer a way to create an empty shared pointer without a lot of typing? Perhaps something analogous to boost::none. I am not using c++11.
Thank you,
Chris
==
using boost::none; using boost::optional;
// declare f(optional<CSomeReallyLongClassName> Item); g(shared_ptr<CSomeReallyLongClassName> pItem);
// invoke f with empty object f(none);
// invoke g with empty object g(shared_ptr<CSomeReallyLongClassName>());
g(0); Ben
On 30/01/2014 15:13, Quoth Ben Pope:
// invoke g with empty object g(shared_ptr<CSomeReallyLongClassName>());
g(0);
Note that (at least in Boost 1.53, haven't checked if this has been changed), .reset(0) is less efficient than .reset() because it still allocates a shared_count to the null pointer. I haven't checked if the constructor has the same issue but it wouldn't surprise me. (Also, the above doesn't compile in 1.53 because the raw pointer constructor is marked explicit. Again, maybe that's been changed in the interim.)
Mere moments ago, quoth I:
On 30/01/2014 15:13, Quoth Ben Pope:
// invoke g with empty object g(shared_ptr<CSomeReallyLongClassName>());
g(0); [...] (Also, the above doesn't compile in 1.53 because the raw pointer constructor is marked explicit. Again, maybe that's been changed in the interim.)
If you're using a C++11 compiler you should be able to use this though: g(nullptr);
On 30/01/14 14:23, Gavin Lambert wrote:
Mere moments ago, quoth I:
On 30/01/2014 15:13, Quoth Ben Pope:
// invoke g with empty object g(shared_ptr<CSomeReallyLongClassName>());
g(0); [...] (Also, the above doesn't compile in 1.53 because the raw pointer constructor is marked explicit. Again, maybe that's been changed in the interim.)
Whoops, You're right. I did test it, but I think I compiled it in C++11 mode!
If you're using a C++11 compiler you should be able to use this though:
g(nullptr);
Yes, of course. Internally boost::shared_ptr uses
boost::detail::sp_nullptr_t, which in C++11 is a typedef of
std::nullptr_t, there appears to be no alternative for C++98, which is a
shame.
I don't see why that type couldn't be defined to an empty struct in
C++98 mode.
Then, removing the #if !defined( BOOST_NO_CXX11_NULLPTR ) guard from the
constructor of shared_ptr that accepts a boost::detail::sp_nullptr_t
does indeed seem to work.
namespace boost {
namespace detail {
struct sp_nullptr_t {};
}
const detail::sp_nullptr_t nullptr = detail::sp_nullptr_t();
}
#include
On 30 January 2014 01:12, Ben Pope
Then, removing the #if !defined( BOOST_NO_CXX11_NULLPTR ) guard from the constructor of shared_ptr that accepts a boost::detail::sp_nullptr_t does indeed seem to work.
namespace boost { namespace detail { struct sp_nullptr_t {}; } const detail::sp_nullptr_t nullptr = detail::sp_nullptr_t(); }
#include
int f(boost::shared_ptr<int> i) { return i ? *i : 0; }
int main() { f(boost::nullptr); }
...there's probably some reason I'm not thinking of.
You can read the paper behind std::nullptr at < http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf>. The short answer is (a) boost::sp_nullptr_t isn't convertible to any pointer or pointer-to-member type, and (b) you really don't want to use boost::nullptr, given that nullptr is a keyword in C++11. -- Nevin ":-)" Liber mailto:nevin@eviloverlord.com (847) 691-1404
On 30 January 2014 10:41, Chris Stankevitz
On Thu, Jan 30, 2014 at 8:18 AM, Nevin Liber
wrote: you really don't want to use boost::nullptr, given that nullptr is a keyword in C++11.
boost::none might be a candidate for this.
Make sure it doesn't interfere with optional< shared_ptr<T> >. The std::optional proposal chose not to use nullptr for good reason. That proposal is at < http://open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3793.html>. IMO, it isn't worth this C++03-only change to shared_ptr just to occasionally save some typing. -- Nevin ":-)" Liber mailto:nevin@eviloverlord.com (847) 691-1404
On 1/30/2014 1:12 AM, Ben Pope wrote:
Yes, of course. Internally boost::shared_ptr uses boost::detail::sp_nullptr_t, which in C++11 is a typedef of std::nullptr_t, there appears to be no alternative for C++98, which is a shame.
I don't see why that type couldn't be defined to an empty struct in C++98 mode.
That works for my own classes: If nullptr_t is not available on the platform, I define a class by that name in my own detail namespace. When defining a class that has a member function taking a parameter of type nullptr_t, no conditional compilation is needed around it, and it finds the definition in the current namespace. If the user of the class defines his own value of type libraryName::nullptr_t, that function can be called. I have not experimented with providing a templated conversion operator to allow libraryName::nullptr_t to be converted to any T*. That should satisfy at least some uses of nullptr literal, although it counts as a user-defined conversion. —John
participants (5)
-
Ben Pope
-
Chris Stankevitz
-
Gavin Lambert
-
John M. Dlugosz
-
Nevin Liber