[smart_ptr] error with nullptr_t

Hi, next follows a compile error with clang 3.1 c++11 just including #include <boost/shared_ptr.hpp> iMac-de-Vicente-Botet-Escriba:test viboes$ time bjam toolset=clang-3.1x ts_ -q ...patience... ...found 1100 targets... ...updating 50 targets... clang-darwin.compile.c++ ../../../bin.v2/libs/thread/test/test_so.test/clang-darwin-3.1x/debug/threading-multi/test_so.o In file included from ../example/test_so.cpp:6: In file included from ../../../boost/shared_ptr.hpp:17: ../../../boost/smart_ptr/shared_ptr.hpp:344:22: error: non-friend class member 'nullptr_t' cannot have a qualified name shared_ptr( std::nullptr_t ) BOOST_NOEXCEPT : px( 0 ), pn() // never throws ~~~~~^ ../../../boost/smart_ptr/shared_ptr.hpp:344:33: error: expected ';' at end of declaration list shared_ptr( std::nullptr_t ) BOOST_NOEXCEPT : px( 0 ), pn() // never throws ^ ;

Vicente J. Botet Escriba wrote:
Hi,
next follows a compile error with clang 3.1 c++11 just including
#include <boost/shared_ptr.hpp>
iMac-de-Vicente-Botet-Escriba:test viboes$ time bjam toolset=clang-3.1x ts_ -q ...patience... ...found 1100 targets... ...updating 50 targets... clang-darwin.compile.c++ ../../../bin.v2/libs/thread/test/test_so.test/clang-darwin-3.1x/debug/threading-multi/test_so.o In file included from ../example/test_so.cpp:6: In file included from ../../../boost/shared_ptr.hpp:17: ../../../boost/smart_ptr/shared_ptr.hpp:344:22: error: non-friend class member 'nullptr_t' cannot have a qualified name shared_ptr( std::nullptr_t ) BOOST_NOEXCEPT : px( 0 ), pn() // never throws ~~~~~^
This is probably another manifestation of the issue with clang supporting the c++11 core language, but the libstdc++ not supporting it, namely, <ctsddef> not defining nullptr_t. I'm not sure how to fix that. !defined(BOOST_NO_CXX11_NULLPTR) does, in my opinion, imply that std::nullptr_t is present (along with nullptr itself). It's not clear how a library could offer nullptr support without using nullptr_t.

Le 11/12/12 20:47, Peter Dimov a écrit :
Vicente J. Botet Escriba wrote:
Hi,
next follows a compile error with clang 3.1 c++11 just including
#include <boost/shared_ptr.hpp>
This is probably another manifestation of the issue with clang supporting the c++11 core language, but the libstdc++ not supporting it, namely, <ctsddef> not defining nullptr_t. I'm not sure how to fix that. !defined(BOOST_NO_CXX11_NULLPTR) does, in my opinion, imply that std::nullptr_t is present (along with nullptr itself). It's not clear how a library could offer nullptr support without using nullptr_t.
Ok, I will update my libc++ installation. Best, Vicente

On 11/12/12 14:47, Peter Dimov wrote:
Vicente J. Botet Escriba wrote:
Hi,
next follows a compile error with clang 3.1 c++11 just including
#include <boost/shared_ptr.hpp>
iMac-de-Vicente-Botet-Escriba:test viboes$ time bjam toolset=clang-3.1x ts_ -q ...patience... ...found 1100 targets... ...updating 50 targets... clang-darwin.compile.c++ ../../../bin.v2/libs/thread/test/test_so.test/clang-darwin-3.1x/debug/threading-multi/test_so.o
In file included from ../example/test_so.cpp:6: In file included from ../../../boost/shared_ptr.hpp:17: ../../../boost/smart_ptr/shared_ptr.hpp:344:22: error: non-friend class member 'nullptr_t' cannot have a qualified name shared_ptr( std::nullptr_t ) BOOST_NOEXCEPT : px( 0 ), pn() // never throws ~~~~~^
This is probably another manifestation of the issue with clang supporting the c++11 core language, but the libstdc++ not supporting it, namely, <ctsddef> not defining nullptr_t. I'm not sure how to fix that. !defined(BOOST_NO_CXX11_NULLPTR) does, in my opinion, imply that std::nullptr_t is present (along with nullptr itself). It's not clear how a library could offer nullptr support without using nullptr_t.
I believe std::nullptr_t could be replaced with decltype(nullptr), which would allow this support to be offered without standard library assistance. John Bytheway

John Bytheway wrote:
I believe std::nullptr_t could be replaced with decltype(nullptr), which would allow this support to be offered without standard library assistance.
Your belief is correct, but I deliberately didn't mention this option for aesthetic reasons. :-) If we're going to support this configuration, I think that the sensible thing to do would be for Boost.Config to define std::nullptr_t, std::move, std::forward, and whatever else is missing and necessary. However... I'm not sure that Boost.Config would be able to detect it.

On 12/11/2012 6:31 PM, Peter Dimov wrote:
John Bytheway wrote:
I believe std::nullptr_t could be replaced with decltype(nullptr), which would allow this support to be offered without standard library assistance.
Your belief is correct, but I deliberately didn't mention this option for aesthetic reasons. :-)
If we're going to support this configuration, I think that the sensible thing to do would be for Boost.Config to define std::nullptr_t, std::move, std::forward, and whatever else is missing and necessary. However... I'm not sure that Boost.Config would be able to detect it.
I just got bit by this. For the record, I don't think it's Boost.Config's business to be defining std::move, std::forward, etc. Another possible alternative would be to do this: namespace boost { typedef decltype(nullptr) nullptr_t; } someplace, maybe in a new Boost.Utility header. Then use boost::nullptr_t instead of std::nullptr_t. Regardless, (speaking as a release manager) I'd like to see this addressed one way or the other since it's a breaking change. -- Eric Niebler BoostPro Computing http://www.boostpro.com

On Wed, Dec 19, 2012 at 8:47 AM, Eric Niebler <eric@boostpro.com> wrote:
On 12/11/2012 6:31 PM, Peter Dimov wrote:
John Bytheway wrote:
I believe std::nullptr_t could be replaced with decltype(nullptr), which would allow this support to be offered without standard library assistance.
Your belief is correct, but I deliberately didn't mention this option for aesthetic reasons. :-)
If we're going to support this configuration, I think that the sensible thing to do would be for Boost.Config to define std::nullptr_t, std::move, std::forward, and whatever else is missing and necessary. However... I'm not sure that Boost.Config would be able to detect it.
I just got bit by this. For the record, I don't think it's Boost.Config's business to be defining std::move, std::forward, etc.
+1, we already have Boost.Move for this.

On Wed, Dec 19, 2012 at 3:01 PM, Peter Dimov <lists@pdimov.com> wrote:
Andrey Semashev wrote:
+1, we already have Boost.Move for this.
Not for this, where "this" is a C++11 compiler without a (complete) C++11 library.
Well, Boost.Move is supposed to "fill the gap" where possible. If we're going to support configurations with C++11 compiler and C++03 STL (which I'm not sure is a good idea, BTW) we might try to detect such cases and define the missing parts ourselves. The necessary code is mostly there.

Peter Dimov wrote:
Not for this, where "this" is a C++11 compiler without a (complete) C++11 library.
I'm sorry for missing this discussion before. If you installed clang 3.1 from MacPorts, which from earlier posts in this thread seems to be the case for Vicente, the solution is to install libc++ from MacPorts and define the following rule in your user-config.jam: using clang : 3.1_11 : clang++-mp-3.1 : <compileflags>-stdlib=libc++ <compileflags>-std=c++11 <linkflags>-stdlib=libc++ ; After that, whenever you want to compile C++11 code with clang just use <toolset>clang-3.1_11 and everything should work as expected. HTH, -Julian

Eric Niebler wrote:
I just got bit by this. For the record, I don't think it's Boost.Config's business to be defining std::move, std::forward, etc.
It's not like this is a first. // BOOST_NO_STDC_NAMESPACE orkaround --------------------------------------// // Because std::size_t usage is so common, even in boost headers which do not // otherwise use the C library, the <cstddef> workaround is included here so // that ugly workaround code need not appear in many other boost headers. // NOTE WELL: This is a workaround for non-conforming compilers; <cstddef> // must still be #included in the usual places so that <cstddef> inclusion // works as expected with standard conforming compilers. The resulting // double inclusion of <cstddef> is harmless. # if defined(BOOST_NO_STDC_NAMESPACE) && defined(__cplusplus) # include <cstddef> namespace std { using ::ptrdiff_t; using ::size_t; } # endif and // BOOST_NO_STD_MIN_MAX orkaround -----------------------------------------// # if defined(BOOST_NO_STD_MIN_MAX) && defined(__cplusplus) namespace std { template <class _Tp> inline const _Tp& min BOOST_PREVENT_MACRO_SUBSTITUTION (const _Tp& __a, const _Tp& __b) { return __b < __a ? __b : __a; } template <class _Tp> inline const _Tp& max BOOST_PREVENT_MACRO_SUBSTITUTION (const _Tp& __a, const _Tp& __b) { return __a < __b ? __b : __a; } } # endif and // When BOOST_NO_STD_TYPEINFO is defined, we can just import // the global definition into std namespace: #if defined(BOOST_NO_STD_TYPEINFO) && defined(__cplusplus) #include <typeinfo> namespace std{ using ::type_info; } #endif

On 19 December 2012 04:47, Eric Niebler <eric@boostpro.com> wrote:
I just got bit by this. For the record, I don't think it's Boost.Config's business to be defining std::move, std::forward, etc. Another possible alternative would be to do this:
namespace boost { typedef decltype(nullptr) nullptr_t; }
someplace, maybe in a new Boost.Utility header. Then use boost::nullptr_t instead of std::nullptr_t.
There's already boost/cstdlib.hpp which is part of utility (although it links to a documentation page that doesn't exist) and boost/cstdint.hpp which is part of the integer library. Messy. I guess adding boost/cstddef.hpp wouldn't be acceptable nowadays, maybe boost/utility/cstddef.hpp?
Regardless, (speaking as a release manager) I'd like to see this addressed one way or the other since it's a breaking change.
What's the way forward? A config/utility ticket? Does anyone want to take responsibility?

Daniel James wrote:
On 19 December 2012 04:47, Eric Niebler <eric@boostpro.com> wrote:
Regardless, (speaking as a release manager) I'd like to see this addressed one way or the other since it's a breaking change.
What's the way forward?
Assuming that we want to support this configuration, the options I see are - Config defining std::nullptr_t as it does with size_t; - Config defining BOOST_NO_NULLPTR_T, so that libraries can activate workarounds, or - SmartPtr fixing the problem somehow without Config involvement, which would entail detecting the problematic configuration in some way.

On Wed, Jan 2, 2013 at 9:49 AM, Peter Dimov <lists@pdimov.com> wrote:
Daniel James wrote:
On 19 December 2012 04:47, Eric Niebler <eric@boostpro.com> wrote:
Regardless, (speaking as a release manager) I'd like to see this addressed one way or the other since it's a breaking change.
What's the way forward?
Would there be a way to determine whether the user is using libstdc++ on the Mac from Boost.Config? I distinctly remember that most standard Mac OS X installations come with a frozen version of libstdc++ (GCC's 4.2) which has patches from Apple. Apple's Clang I supports C++11 but only really works if you link with libc++ (or maybe if you get an updated libstdc++ with patches to work on OS X with clang). Being able to check the version of libstdc++ being used should give you a better way of making this determination.
Assuming that we want to support this configuration, the options I see are
- Config defining std::nullptr_t as it does with size_t;
I'm ambivalent about this FWIW.
- Config defining BOOST_NO_NULLPTR_T, so that libraries can activate workarounds, or
This looks like the better situation.
- SmartPtr fixing the problem somehow without Config involvement, which would entail detecting the problematic configuration in some way.
If the check for clang+libstdc++ can be localised in SmartPtr, this would make sense but I think it's not going to be the only thing that will run into this issue. Just my A$0.05. -- Dean Michael Berris www.deanberris.com

Dean Michael Berris wrote:
Would there be a way to determine whether the user is using libstdc++ on the Mac from Boost.Config?
I distinctly remember that most standard Mac OS X installations come with a frozen version of libstdc++ (GCC's 4.2) which has patches from Apple. Apple's Clang I supports C++11 but only really works if you link with libc++ (or maybe if you get an updated libstdc++ with patches to work on OS X with clang). Being able to check the version of libstdc++ being used should give you a better way of making this determination.
This is what libstdcpp3.hpp has to say on the matter: // stdlibc++ C++0x support is detected via __GNUC__, __GNUC_MINOR__, and possibly // __GNUC_PATCHLEVEL__ at the suggestion of Jonathan Wakely, one of the stdlibc++ // developers. He also commented: // // "I'm not sure how useful __GLIBCXX__ is for your purposes, for instance in // GCC 4.2.4 it is set to 20080519 but in GCC 4.3.0 it is set to 20080305. // Although 4.3.0 was released earlier than 4.2.4, it has better C++0x support // than any release in the 4.2 series." // // Another resource for understanding stdlibc++ features is: // http://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#manual.intro.stat... It uses the compiler version to determine library features. Now... according to gcc.hpp, nullptr (and by assumption std::nullptr_t) first appeared in g++ 4.6, so if we set BOOST_NO_CXX11_NULLPTR_T for pre-4.6 in libstdcpp3.hpp and if Apple's clang defines its GCC version as 4.2, as I suspect it would, then it might work. But I have no way to check.

On 1 January 2013 22:49, Peter Dimov <lists@pdimov.com> wrote:
Daniel James wrote:
On 19 December 2012 04:47, Eric Niebler <eric@boostpro.com> wrote:
Regardless, (speaking as a release manager) I'd like to see this addressed one way or the other since it's a breaking change.
What's the way forward?
Assuming that we want to support this configuration, the options I see are
I was asking more about how (or perhaps, who) to get started on a fix/workaround.
- Config defining std::nullptr_t as it does with size_t; - Config defining BOOST_NO_NULLPTR_T, so that libraries can activate workarounds, or
If you want to add something to config, it might be a good idea to write that in a post with [config] in the subject line, or to open a ticket. Although I prefer Eric's boost::nullptr_t, adding things to 'std' is a bad idea, precedents notwithstanding.

Daniel James wrote:
On 19 December 2012 04:47, Eric Niebler <eric@boostpro.com> wrote:
Regardless, (speaking as a release manager) I'd like to see this addressed one way or the other since it's a breaking change.
What's the way forward? A config/utility ticket? Does anyone want to take responsibility?
Please see revision [82351] on trunk. I'll appreciate it if someone using Clang with libstdc++ 4.2 tests it and reports whether it fixes the problem, or if not, what needs to be done. Once this is confirmed as an acceptable and working fix, let me know if it should be merged to release.

On 4 January 2013 15:45, Peter Dimov <lists@pdimov.com> wrote:
Please see revision [82351] on trunk. I'll appreciate it if someone using Clang with libstdc++ 4.2 tests it and reports whether it fixes the problem, or if not, what needs to be done.
Seems to work okay. I ran the smart_ptr and had some failures due to std::move being used in tests. Quickbook (which is where I noticed this) works fine.

Le 04/01/13 18:26, Daniel James a écrit :
Please see revision [82351] on trunk. I'll appreciate it if someone using Clang with libstdc++ 4.2 tests it and reports whether it fixes the problem, or if not, what needs to be done. Seems to work okay. I ran the smart_ptr and had some failures due to std::move being used in tests. Quickbook (which is where I noticed
On 4 January 2013 15:45, Peter Dimov <lists@pdimov.com> wrote: this) works fine.
Hi, it seems that the issue is resolved for smart_ptr. Unfortunately Boost.Test use indiscriminately C++11 library features as enable_if, forward unconditionally. Best, Vicente

Peter Dimov wrote:
Please see revision [82351] on trunk. I'll appreciate it if someone using Clang with libstdc++ 4.2 tests it and reports whether it fixes the problem, or if not, what needs to be done.
A few comments: * `defined(BOOST_CLANG)` would be safer than `defined(__clang__)` after resolving #7359 ( https://svn.boost.org/trac/boost/ticket/7359 ); it seems that Intel compiler can define `__clang__`. * If you want to use std::nullptr_t on clang with libstdc++ newer than 4.2, you can use defined(__GLIBCXX__) && !(__GLIBCXX__ >= 20080306 && __GLIBCXX__ != 20080519) instead of `!defined( _LIBCPP_VERSION )`. I used this (ugly) version check to detect the availability of clang's type-traits intrinsics in boost/type_traits/intrinsics.hpp. But please note that when using with clang, Boost.Config does not recognize the correct version of libstdc++ (#7473 https://svn.boost.org/trac/boost/ticket/7473 ). Regards, Michel

Michel Morin wrote:
A few comments: * `defined(BOOST_CLANG)` would be safer than `defined(__clang__)` after resolving #7359 ( https://svn.boost.org/trac/boost/ticket/7359 ); it seems that Intel compiler can define `__clang__`.
We cannot say `defined(BOOST_CLANG)` would be safer in this case. Please ignore my previous post, sorry. Regards, Michel

Michel Morin wrote:
* If you want to use std::nullptr_t on clang with libstdc++ newer than 4.2, you can use defined(__GLIBCXX__) && !(__GLIBCXX__ >= 20080306 && __GLIBCXX__ != 20080519)
That looks almost certainly wrong, as g++ (and presumably libstdc++) doesn't have nullptr support until version 4.6.

Peter Dimov wrote:
Michel Morin wrote:
* If you want to use std::nullptr_t on clang with libstdc++ newer than 4.2, you can use defined(__GLIBCXX__) && !(__GLIBCXX__ >= 20080306 && __GLIBCXX__ != 20080519)
That looks almost certainly wrong, as g++ (and presumably libstdc++) doesn't have nullptr support until version 4.6.
You're right; that condition is wrong. Sorry, again, for the noise. Regards, Michel
participants (9)
-
Andrey Semashev
-
Daniel James
-
Dean Michael Berris
-
Eric Niebler
-
John Bytheway
-
Julian Gonggrijp
-
Michel Morin
-
Peter Dimov
-
Vicente J. Botet Escriba