[config] request for BOOST_NO_FWD_STD_DECLARATION

libc++ does not allow forward declarations of types for std:: , as it uses inline namespace to allow versioning. Forward declarations occur in many libraries (config, fusion, interprocess). In each case I would like to just include the actual headers. I could just #define all cases for LIBCPP, but other libraries might move to using inline namespaces in future, so I could introduce a macro? Chris

libc++ does not allow forward declarations of types for std:: , as it uses inline namespace to allow versioning.
Forward declarations occur in many libraries (config, fusion, interprocess). In each case I would like to just include the actual headers.
I could just #define all cases for LIBCPP, but other libraries might move to using inline namespaces in future, so I could introduce a macro?
I think that sounds a reasonable addition, yes. Do you have patches? John.

On 16 February 2011 09:40, John Maddock <boost.regex@virgin.net> wrote:
libc++ does not allow forward declarations of types for std:: , as it uses inline namespace to allow versioning.
Forward declarations occur in many libraries (config, fusion, interprocess). In each case I would like to just include the actual headers.
I could just #define all cases for LIBCPP, but other libraries might move to using inline namespaces in future, so I could introduce a macro?
I think that sounds a reasonable addition, yes. Do you have patches?
IMO it should be a macro that's defined when forward declaration is possible rather than when it isn't. That way the default would be the safer option. I now think it was a mistake to forward declare for unknown setups in 'container_fwd.hpp'. Daniel

On 16 Feb 2011, at 12:52, Daniel James wrote:
On 16 February 2011 09:40, John Maddock <boost.regex@virgin.net> wrote:
libc++ does not allow forward declarations of types for std:: , as it uses inline namespace to allow versioning.
Forward declarations occur in many libraries (config, fusion, interprocess). In each case I would like to just include the actual headers.
I could just #define all cases for LIBCPP, but other libraries might move to using inline namespaces in future, so I could introduce a macro?
I think that sounds a reasonable addition, yes. Do you have patches?
IMO it should be a macro that's defined when forward declaration is possible rather than when it isn't. That way the default would be the safer option. I now think it was a mistake to forward declare for unknown setups in 'container_fwd.hpp'.
I would be happy with that, except I note that (for example) boost fusion currently unconditionally forward declares std::pair, and every compiler in the regression test (except clang with libc++) passes the std_pair test. Therefore the macro would have to be added to every other compiler, else they would become less efficent. Chris

libc++ does not allow forward declarations of types for std:: , as it uses inline namespace to allow versioning.
Forward declarations occur in many libraries (config, fusion, interprocess). In each case I would like to just include the actual headers.
I could just #define all cases for LIBCPP, but other libraries might move to using inline namespaces in future, so I could introduce a macro?
I think that sounds a reasonable addition, yes. Do you have patches?
IMO it should be a macro that's defined when forward declaration is possible rather than when it isn't. That way the default would be the safer option. I now think it was a mistake to forward declare for unknown setups in 'container_fwd.hpp'.
I would be happy with that, except I note that (for example) boost fusion currently unconditionally forward declares std::pair, and every compiler in the regression test (except clang with libc++) passes the std_pair test. Therefore the macro would have to be added to every other compiler, else they would become less efficent.
Note that since this is std lib issue, and since there are only a few std lib's out there, it's not that much of a change to Boost.Config to add this to every std lib config except libc++ (if indeed that's what's required). As others have noted, in principle this isn't std conforming, just useful. John.

On 16 February 2011 07:40, John Maddock <boost.regex@virgin.net> wrote:
libc++ does not allow forward declarations of types for std:: , as it uses
inline namespace to allow versioning.
Forward declarations occur in many libraries (config, fusion, interprocess). In each case I would like to just include the actual headers.
As others have noted, in principle this isn't std conforming, just useful.
I find forwarding of std::containers very useful, and have needed to write my own in the past (of course, nonportable). There's are a big overlap in different boost libraries that does the same, and for users such as myself. Can't this be taken one step further, and introduce something like boost/details/stdfwd.hpp, or maybe boost/stdfwd.hpp? In the case where forwarding is not possible, stdfwd.hpp would have to include all std::containers - Christian

Christian Holmquist wrote:
I find forwarding of std::containers very useful, and have needed to write my own in the past (of course, nonportable). There's are a big overlap in different boost libraries that does the same, and for users such as myself.
Can't this be taken one step further, and introduce something like boost/details/stdfwd.hpp, or maybe boost/stdfwd.hpp? In the case where forwarding is not possible, stdfwd.hpp would have to include all std::containers
In the fallback case, you'd force inclusion of <map>, <multimap>, <set>, etc. for some context that, otherwise, would only have included, say, <vector>. That's not a good tradeoff. Instead of stdfwd.hpp, it'll have to be map_fwd.hpp, multimap_fwd.hpp, and so on. _____ 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.

On 16 February 2011 14:41, Stewart, Robert <Robert.Stewart@sig.com> wrote:
Christian Holmquist wrote:
Can't this be taken one step further, and introduce something like boost/details/stdfwd.hpp, or maybe boost/stdfwd.hpp? In the case where forwarding is not possible, stdfwd.hpp would have to include all std::containers
In the fallback case, you'd force inclusion of <map>, <multimap>, <set>, etc. for some context that, otherwise, would only have included, say, <vector>. That's not a good tradeoff. Instead of stdfwd.hpp, it'll have to be map_fwd.hpp, multimap_fwd.hpp, and so on.
We've already got such a thing, it's called 'boost/detail/container_fwd.hpp'. It deals with all the containers because it was originally written for the hash library, which needs them all. But IMO If you just want a single container, you might as well just include the header. They're not that expensive. Daniel

Can't this be taken one step further, and introduce something like boost/details/stdfwd.hpp, or maybe boost/stdfwd.hpp? In the case where forwarding is not possible, stdfwd.hpp would have to include all std::containers
In the fallback case, you'd force inclusion of <map>, <multimap>, <set>, etc. for some context that, otherwise, would only have included, say, <vector>. That's not a good tradeoff. Instead of stdfwd.hpp, it'll have to be map_fwd.hpp, multimap_fwd.hpp, and so on.
We've already got such a thing, it's called 'boost/detail/container_fwd.hpp'. It deals with all the containers because it was originally written for the hash library, which needs them all. But IMO If you just want a single container, you might as well just include the header. They're not that expensive.
In which case do we need to do anything - other than make the libraries that should use that header but don't, use it? John.

On 16 Feb 2011, at 16:56, John Maddock wrote:
Can't this be taken one step further, and introduce something like boost/details/stdfwd.hpp, or maybe boost/stdfwd.hpp? In the case where forwarding is not possible, stdfwd.hpp would have to include all std::containers
In the fallback case, you'd force inclusion of <map>, <multimap>, <set>, etc. for some context that, otherwise, would only have included, say, <vector>. That's not a good tradeoff. Instead of stdfwd.hpp, it'll have to be map_fwd.hpp, multimap_fwd.hpp, and so on.
We've already got such a thing, it's called 'boost/detail/container_fwd.hpp'. It deals with all the containers because it was originally written for the hash library, which needs them all. But IMO If you just want a single container, you might as well just include the header. They're not that expensive.
In which case do we need to do anything - other than make the libraries that should use that header but don't, use it?
This might pull in a lot more than those libraries need, particularly in the case where we don't use the forward declarations, but pull in all the headers. In the extreme case some places just want pair (although they could just include <utility>) Chris

We've already got such a thing, it's called 'boost/detail/container_fwd.hpp'. It deals with all the containers because it was originally written for the hash library, which needs them all. But IMO If you just want a single container, you might as well just include the header. They're not that expensive.
In which case do we need to do anything - other than make the libraries that should use that header but don't, use it?
This might pull in a lot more than those libraries need, particularly in the case where we don't use the forward declarations, but pull in all the headers. In the extreme case some places just want pair (although they could just include <utility>)
Well they might... but shouldn't we doing something like: * If you need several, use container_fwd.hpp. * If you need one, just include the necessary header (forward declaring pair is just plain silly IMO). * If you need two, then choose which is worst - including two std lib headers or container_fwd.hpp. John.

On 16 Feb 2011, at 17:10, John Maddock wrote:
We've already got such a thing, it's called 'boost/detail/container_fwd.hpp'. It deals with all the containers because it was originally written for the hash library, which needs them all. But IMO If you just want a single container, you might as well just include the header. They're not that expensive.
In which case do we need to do anything - other than make the libraries that should use that header but don't, use it?
This might pull in a lot more than those libraries need, particularly in the case where we don't use the forward declarations, but pull in all the headers. In the extreme case some places just want pair (although they could just include <utility>)
Well they might... but shouldn't we doing something like:
* If you need several, use container_fwd.hpp. * If you need one, just include the necessary header (forward declaring pair is just plain silly IMO). * If you need two, then choose which is worst - including two std lib headers or container_fwd.hpp.
So, the main current problem (interprocess) template <class T> class allocator; template <class T> struct less; template <class T1, class T2> struct pair; template <class CharType> struct char_traits; We should just pull in? #include <utility> #include <memory> #include <functional> #include <iosfwd> None of those headers is that big, we avoid a big io header with iosfwd. Chris

On 16 February 2011 18:34, Christopher Jefferson <chris@bubblescope.net> wrote:
So, the main current problem (interprocess)
You should ask on a new thread with '[interprocess]' in the title, or post a ticket. Ion probably won't be reading this thread. I'm not against splitting up container_fwd.hpp if that's what people want. Daniel

El 16/02/2011 19:40, Daniel James escribió:
On 16 February 2011 18:34, Christopher Jefferson<chris@bubblescope.net> wrote:
So, the main current problem (interprocess)
You should ask on a new thread with '[interprocess]' in the title, or post a ticket. Ion probably won't be reading this thread.
I'm not against splitting up container_fwd.hpp if that's what people want.
I've received the ticket. I have no problem to use a std predeclaration file like boost/detail/container_fwd.hpp, but shouldn't those predeclarations contain default parameters? I would need to predeclare allocator, less, and char_traits so that I can use them as default parameters in my own interprocess predeclarations. And can't we predeclare libc++ types in the correct namespace, use inline namespaces and avoid any header inclusion? Best, Ion

On 16 Feb 2011, at 22:12, Ion Gaztañaga wrote:
El 16/02/2011 19:40, Daniel James escribió:
On 16 February 2011 18:34, Christopher Jefferson<chris@bubblescope.net> wrote:
So, the main current problem (interprocess)
You should ask on a new thread with '[interprocess]' in the title, or post a ticket. Ion probably won't be reading this thread.
I'm not against splitting up container_fwd.hpp if that's what people want.
I've received the ticket. I have no problem to use a std predeclaration file like boost/detail/container_fwd.hpp, but shouldn't those predeclarations contain default parameters?
No, with templates you only get to declare the default parameters once, so you must not put them on. if you do, including the real std header later doesn't compile.
I would need to predeclare allocator, less, and char_traits so that I can use them as default parameters in my own interprocess predeclarations.
And can't we predeclare libc++ types in the correct namespace, use inline namespaces and avoid any header inclusion?
While I don't speak for libc++, I believe their preference is to not do this, as then if they change the names of the inline namespaces later, it would break boost. Just include the headers instead. Of course, this shouldn't be imposed on all compilers if it leads to an unacceptable slowdown. It does lead to a massive increase in a pre-processed interprocess_fwd.hpp. Unfortunately the set of things required by interprocess is from various different headers, it wouldn't want to pull in 'container_fwd.hpp'. I'm not sure if there is demand for a full-blown set of forward declarations for all the standard library. My preference would be a BOOST_CAN_FORWARD_DECLARE_STD macro, and pulling in the real headers in interprocess_fwd.hpp when it isn't defined. Chris

On Feb 16, 2011, at 5:51 PM, Christopher Jefferson wrote:
On 16 Feb 2011, at 22:12, Ion Gaztañaga wrote:
El 16/02/2011 19:40, Daniel James escribió:
On 16 February 2011 18:34, Christopher Jefferson<chris@bubblescope.net> wrote:
So, the main current problem (interprocess)
You should ask on a new thread with '[interprocess]' in the title, or post a ticket. Ion probably won't be reading this thread.
I'm not against splitting up container_fwd.hpp if that's what people want.
I've received the ticket. I have no problem to use a std predeclaration file like boost/detail/container_fwd.hpp, but shouldn't those predeclarations contain default parameters?
No, with templates you only get to declare the default parameters once, so you must not put them on. if you do, including the real std header later doesn't compile.
Right.
I would need to predeclare allocator, less, and char_traits so that I can use them as default parameters in my own interprocess predeclarations.
And can't we predeclare libc++ types in the correct namespace, use inline namespaces and avoid any header inclusion?
While I don't speak for libc++, I believe their preference is to not do this, as then if they change the names of the inline namespaces later, it would break boost. Just include the headers instead.
Of course, this shouldn't be imposed on all compilers if it leads to an unacceptable slowdown. It does lead to a massive increase in a pre-processed interprocess_fwd.hpp. Unfortunately the set of things required by interprocess is from various different headers, it wouldn't want to pull in 'container_fwd.hpp'.
I'm not sure if there is demand for a full-blown set of forward declarations for all the standard library. My preference would be a BOOST_CAN_FORWARD_DECLARE_STD macro, and pulling in the real headers in interprocess_fwd.hpp when it isn't defined.
I have no objection to boost doing this. But yes, libc++ will break such practice every time the ABI changes, which should be more often than never, and less often than every once in a while. Furthermore, it is quite possible, even likely, that a single implementation will ship with more than one ABI at a time (different inlined namespaces - version 1, version 2, etc.). If you want to use it, libc++ has the following macros: _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD which do the inline namespace dance. Be forewarned that some symbols are /not/ versioned. I.e. they really are in namespace std. Currently that is operator new/delete, the set handler functions, and the C++03 std-defined exception classes. This set of non-versioned symbols is also subject to change. There will be no backward compatibility concerns for clients forward declaring std::items. The best way to address this issue is to bring it to the LWG. Bring performance impact measurements. -Howard

El 17/02/2011 0:07, Howard Hinnant escribió:
On Feb 16, 2011, at 5:51 PM, Christopher Jefferson wrote:
No, with templates you only get to declare the default parameters once, so you must not put them on. if you do, including the real std header later doesn't compile.
Right.
Sorry for the mistake, it's a real pity that we can't use container predeclarations to declare something like: void func(const std::vector<int> &inputs);
The best way to address this issue is to bring it to the LWG. Bring performance impact measurements.
Yes. I think there is need for this, having to include a lot of std headers to declare a function with a std::string const reference as input parameter is a bit too much. In the meantime Boost could offer compiler-ABI-dependent predeclarations, but for standard predeclaration headers I think they should also offer default parameters. Best, Ion

Le samedi 19 février 2011 à 19:37 +0100, Ion Gaztañaga a écrit :
having to include a lot of std headers to declare a function with a std::string const reference as input parameter is a bit too much
For a function declaration, even when you pass/return by value, you only need to declare types. Regards, Ivan

Ivan Le Lann wrote:
Le samedi 19 février 2011 à 19:37 +0100, Ion Gaztañaga a écrit :
having to include a lot of std headers to declare a function with a std::string const reference as input parameter is a bit too much
For a function declaration, even when you pass/return by value, you only need to declare types.
That's true unless, as is the subject of this thread, the type you would like to forward declare is in namespace std. Then you get into the world of "as if." The implementer may declare std types with template parameters beyond those named in the standard, provided the extras are defaulted so the types work as if they didn't have the extra template parameters. If a type does have extra template parameters, however, forward declaring it without them means mismatching the declarations while including them means requires that they be defaulted correctly. Unfortunately, defaults can be specified only once. Only std types that don't make use of defaulted template parameters could be forward declared and, even then, are nonportable, even among versions of the same standard library. _____ 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.

On Tue, 22 Feb 2011 18:20:14 +0500, Stewart, Robert <Robert.Stewart@sig.com> wrote:
[snip] The implementer may declare std types with template parameters beyond those named in the standard, provided the extras are defaulted so the types work as if they didn't have the extra template parameters.
No. See http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#94
[snip]

Ilya Sokolov wrote:
On Tue, 22 Feb 2011 18:20:14 +0500, Stewart, Robert <Robert.Stewart@sig.com> wrote:
The implementer may declare std types with template parameters beyond those named in the standard, provided the extras are defaulted so the types work as if they didn't have the extra template parameters.
No. See http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#94
I think the committee was disingenuous to declare the standard clear as written when Pete Becker got it wrong: http://bit.ly/hXpupO. Still, that issue does prove me wrong. Thanks for the clarification. _____ 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.

On Thu, 24 Feb 2011 21:00:05 +0500, Stewart, Robert <Robert.Stewart@sig.com> wrote:
Ilya Sokolov wrote:
On Tue, 22 Feb 2011 18:20:14 +0500, Stewart, Robert <Robert.Stewart@sig.com> wrote:
The implementer may declare std types with template parameters beyond those named in the standard, provided the extras are defaulted so the types work as if they didn't have the extra template parameters.
No. See http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-closed.html#94
I think the committee was disingenuous to declare the standard clear as written when Pete Becker got it wrong: http://bit.ly/hXpupO.
+1. Looks like 'clear as written' means something else for the committee ).
Still, that issue does prove me wrong. Thanks for the clarification.
_____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com

On 16 February 2011 22:51, Christopher Jefferson <chris@bubblescope.net> wrote:
On 16 Feb 2011, at 22:12, Ion Gaztañaga wrote:
I would need to predeclare allocator, less, and char_traits so that I can use them as default parameters in my own interprocess predeclarations.
allocator and char_traits are already declared. Adding less shouldn't be a problem.
And can't we predeclare libc++ types in the correct namespace, use inline namespaces and avoid any header inclusion?
While I don't speak for libc++, I believe their preference is to not do this, as then if they change the names of the inline namespaces later, it would break boost. Just include the headers instead.
I wouldn't want to deal with anything defined in a nested namespace. Strikes me as more trouble than it's worth. But if someone else wants to take over....
Of course, this shouldn't be imposed on all compilers if it leads to an unacceptable slowdown. It does lead to a massive increase in a pre-processed interprocess_fwd.hpp. Unfortunately the set of things required by interprocess is from various different headers, it wouldn't want to pull in 'container_fwd.hpp'.
I'm not sure if there is demand for a full-blown set of forward declarations for all the standard library. My preference would be a BOOST_CAN_FORWARD_DECLARE_STD macro, and pulling in the real headers in interprocess_fwd.hpp when it isn't defined.
I have no preference. We could break up the header if necessary. The main issue was dealing with individual library weirdness. But that is a lot less of a problem nowadays - the libraries were often a bit odd to deal with compiler bugs or unsupported features, but we don't really support such compilers anymore. So nowadays in most cases the issue is warnings caused by differences in the declaration, such as the clang check for complex in the header (which should have been done based on library). Daniel

On 16 February 2011 13:13, Christopher Jefferson <chris@bubblescope.net> wrote:
I would be happy with that, except I note that (for example) boost fusion currently unconditionally forward declares std::pair, and every compiler in the regression test (except clang with libc++) passes the std_pair test. Therefore the macro would have to be added to every other compiler, else they would become less efficent.
Codegear fails the test. Bit you can't extrapolate from std::pair to the containers, since they often have alternative implementations (e.g. gcc's debug and parallel versions). My plan is to change container_fwd to not forward declare by default, and add a test to check for setups where it's possible to forward declare but I'm not doing it. Foward declaring std::pair is usually a little pointless anyway, since config includes utility for most libraries. I know I do it, I only just realised. Daniel

On 16 Feb 2011, at 13:44, Daniel James wrote:
On 16 February 2011 13:13, Christopher Jefferson <chris@bubblescope.net> wrote:
I would be happy with that, except I note that (for example) boost fusion currently unconditionally forward declares std::pair, and every compiler in the regression test (except clang with libc++) passes the std_pair test. Therefore the macro would have to be added to every other compiler, else they would become less efficent.
Codegear fails the test. Bit you can't extrapolate from std::pair to the containers, since they often have alternative implementations (e.g. gcc's debug and parallel versions). My plan is to change container_fwd to not forward declare by default, and add a test to check for setups where it's possible to forward declare but I'm not doing it.
Foward declaring std::pair is usually a little pointless anyway, since config includes utility for most libraries. I know I do it, I only just realised.
Problems I am currently aware of: detail/container_fwd.hpp has a huge list of special cases already. These could be folded into a new macro definition boost/interprocess/containers/container/container_fwd.hpp has forward definitions for a few standard library types, currently unconditionally. boost/interprocess/interprocess_fwd.hpp has the same forward declarations. boost/fusion/adapted/std_pair.hpp forward defines std::pair. There are a bunch of other abuses of std in boost (mainly injecting names into std), but they are a different problem, and not currently causing any issues. So, the obvious steps are: introduce BOOST_ALLOW_FORWARD_STD (?) and use it to wrap all the above includes. Looking at the current top of container_fwd.hpp: #if defined(BOOST_DETAIL_NO_CONTAINER_FWD) \ || ((defined(__GLIBCPP__) || defined(__GLIBCXX__)) \ && (defined(_GLIBCXX_DEBUG) || defined(_GLIBCXX_PARALLEL))) \ || BOOST_WORKAROUND(__BORLANDC__, > 0x551) \ || BOOST_WORKAROUND(__DMC__, BOOST_TESTED_AT(0x842)) \ || (defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) Note that BOOST_DETAIL_NO_CONTAINER_FWD seems to be a macro for testing, not one to be set. Probably push all those current bits into the appropriate compiler / library headers. This would mean that we would stop the forward declarations in fusion and interprocess whenever any of the above macros are defined, but that might be a good idea anyway. I'm happy to try to put together the necessary config changes for this, I just wanted to discuss it because it is poking at a large range of compilers and libraries, not just a few #ifdefs for libc++ anymore. Chris

On 16 February 2011 14:36, Christopher Jefferson <chris@bubblescope.net> wrote:
#if defined(BOOST_DETAIL_NO_CONTAINER_FWD) \ || ((defined(__GLIBCPP__) || defined(__GLIBCXX__)) \ && (defined(_GLIBCXX_DEBUG) || defined(_GLIBCXX_PARALLEL))) \ || BOOST_WORKAROUND(__BORLANDC__, > 0x551) \ || BOOST_WORKAROUND(__DMC__, BOOST_TESTED_AT(0x842)) \ || (defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION))
Note that BOOST_DETAIL_NO_CONTAINER_FWD seems to be a macro for testing, not one to be set.
It was added to allow users to disable container declaration. Daniel

On 16 Feb 2011, at 12:35, Mathias Gaunard wrote:
On 15/02/2011 21:54, Christopher Jefferson wrote:
libc++ does not allow forward declarations of types for std:: , as it uses inline namespace to allow versioning.
Is that legal?
I think so. I believe it is impossible to tell, except when trying to do forward declarations of C++ standard library types. The question is then if forward declarations of types in std:: are allowed. From 17.6.3.2.1p1 in the current C++0x draft (there is identical text in the c++03 standard): "The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified." While people could read this in various ways, I would say it forbids these kinds of games, although they might work for particular standard libraries.

On 16/02/2011 13:52, Christopher Jefferson wrote:
On 16 Feb 2011, at 12:35, Mathias Gaunard wrote:
On 15/02/2011 21:54, Christopher Jefferson wrote:
libc++ does not allow forward declarations of types for std:: , as it uses inline namespace to allow versioning.
Is that legal?
I think so. I believe it is impossible to tell, except when trying to do forward declarations of C++ standard library types.
The question is then if forward declarations of types in std:: are allowed. From 17.6.3.2.1p1 in the current C++0x draft (there is identical text in the c++03 standard):
"The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified."
While people could read this in various ways, I would say it forbids these kinds of games, although they might work for particular standard libraries.
The standard also gives the reference of what the declarations of the classes of the standard library must be, and all those declarations are in namespace std.

On 16 February 2011 14:49, Mathias Gaunard <mathias.gaunard@ens-lyon.org> wrote:
The standard also gives the reference of what the declarations of the classes of the standard library must be, and all those declarations are in namespace std.
There are people here who'll know better than me, but I believe the implementer only has to make the class behave as if it was defined in the same way as the standard definition. They don't have to match the declarations exactly. If the only way to detect this is by doing something non-standard (such as declaring in 'std') then it's legit. Daniel

On 16 Feb 2011, at 14:57, Daniel James wrote:
On 16 February 2011 14:49, Mathias Gaunard <mathias.gaunard@ens-lyon.org> wrote:
The standard also gives the reference of what the declarations of the classes of the standard library must be, and all those declarations are in namespace std.
There are people here who'll know better than me, but I believe the implementer only has to make the class behave as if it was defined in the same way as the standard definition. They don't have to match the declarations exactly. If the only way to detect this is by doing something non-standard (such as declaring in 'std') then it's legit.
i think you are right. On a practical note, while I don't speak for the authors of libc++, or anyone else other than myself, inline namespaces seem to be the best way to tackle a major problem in C++, which is allowing multiple binary-incompatable versions of libraries to exist without horrible issues involving breaking the one definition rule. Even if subtle readings of the standard turned out to forbid it, using inline namespaces to implement std:: is here to stay, and I expect it to get more popular as time goes by. Chris

Le 16/02/2011 16:06, Christopher Jefferson a écrit :
Even if subtle readings of the standard turned out to forbid it, using inline namespaces to implement std:: is here to stay, and I expect it to get more popular as time goes by.
My question is more the following: Should'nt forward declaration work even if the element turns out to be inside an inline namespace ? -- Loïc

On 16 Feb 2011, at 15:18, Loïc Joly wrote:
Le 16/02/2011 16:06, Christopher Jefferson a écrit :
Even if subtle readings of the standard turned out to forbid it, using inline namespaces to implement std:: is here to stay, and I expect it to get more popular as time goes by.
My question is more the following: Should'nt forward declaration work even if the element turns out to be inside an inline namespace ?
It can't do, practically (random details follow) The main purposes of inline namespaces is that the name of the inline namespace gets mangled into the object name, so namespace std { inline namespace version1 { struct pair; } } void my_function(std::pair); The compiler creates a "mangled" string, which represents uniquely this function, including it's name and all the types it accepts. This is used by the linker to connect together calls to functions, and the function definitions. It is something like (but not, as this is a simple example): _Fmy_function__Pstd__version1_pair. Now when we do a new version we define: namespace std { inline namespace version2 { struct pair; } } then my_function gets mangled to _Fmy_function__Pstd__version2_pair. This has lots of advantages. Code which uses both my_function on a version1 pair and version 2 pair works, and calls the right my_function. If you have a library which has a my_function compiled for a version1 std::pair, and try to call it from code which uses version 2, you will get a link-time failure. If the "mangled name" of both pairs were the same, linking would work but if the version1 pair and version2 pair did not have the same binary layout, horrible things would happen. This means that if we just see: namespace std { struct pair; }, we can't know which inline namespace to put it in. The only way to make this work would be to not mangle the name of the inline namespace into the object, which would defeat the purpose. Chris

Le 16/02/2011 16:30, Christopher Jefferson a écrit :
It can't do, practically (random details follow)
The main purposes of inline namespaces is that the name of the inline namespace gets mangled into the object name, so
namespace std { inline namespace version1 { struct pair; } }
void my_function(std::pair);
The compiler creates a "mangled" string, which represents uniquely this function, including it's name and all the types it accepts. This is used by the linker to connect together calls to functions, and the function definitions.
Ok, I was being dense, and did only consider for instance the use of a pair* in a class definition, which is internal, not the use of pair in function declaration, where it is exported. So, if user cannot forward with inline namespaces, and implementers really need inline namespaces, I guess the only solution would be to require implementers special forwarding headers, but I'm afraid it's too late for that...

On 16.02.2011, at 16:18, Loïc Joly wrote:
Le 16/02/2011 16:06, Christopher Jefferson a écrit :
Even if subtle readings of the standard turned out to forbid it, using inline namespaces to implement std:: is here to stay, and I expect it to get more popular as time goes by.
My question is more the following: Should'nt forward declaration work even if the element turns out to be inside an inline namespace ?
No. Those would still declare different things. Sebastian

On 16.02.2011, at 15:49, Mathias Gaunard wrote:
On 16/02/2011 13:52, Christopher Jefferson wrote:
On 16 Feb 2011, at 12:35, Mathias Gaunard wrote:
On 15/02/2011 21:54, Christopher Jefferson wrote:
libc++ does not allow forward declarations of types for std:: , as it uses inline namespace to allow versioning.
Is that legal?
I think so. I believe it is impossible to tell, except when trying to do forward declarations of C++ standard library types.
The question is then if forward declarations of types in std:: are allowed. From 17.6.3.2.1p1 in the current C++0x draft (there is identical text in the c++03 standard):
"The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified."
While people could read this in various ways, I would say it forbids these kinds of games, although they might work for particular standard libraries.
The standard also gives the reference of what the declarations of the classes of the standard library must be, and all those declarations are in namespace std.
It also contains this in C++0x 17.6.1.1p2: "It is unspecified whether names declared in a specific namespace are declared directly in that namespace or in an inline namespace inside that namespace." Sebastian

On Wed, Feb 16, 2011 at 12:49 PM, Mathias Gaunard <mathias.gaunard@ens-lyon.org> wrote:
On 16/02/2011 13:52, Christopher Jefferson wrote:
[snip]
The question is then if forward declarations of types in std:: are allowed. From 17.6.3.2.1p1 in the current C++0x draft (there is identical text in the c++03 standard):
"The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified."
While people could read this in various ways, I would say it forbids these kinds of games, although they might work for particular standard libraries.
The standard also gives the reference of what the declarations of the classes of the standard library must be, and all those declarations are in namespace std.
Isn't the standard library allowed to add template parameters with defaults? template <typename T, typename Allocator, typename _InternalParameter = int> struct vector; -- Felipe Magno de Almeida

On 22 Feb 2011, at 13:28, Felipe Magno de Almeida wrote:
On Wed, Feb 16, 2011 at 12:49 PM, Mathias Gaunard <mathias.gaunard@ens-lyon.org> wrote:
On 16/02/2011 13:52, Christopher Jefferson wrote:
[snip]
The question is then if forward declarations of types in std:: are allowed. From 17.6.3.2.1p1 in the current C++0x draft (there is identical text in the c++03 standard):
"The behavior of a C++ program is undefined if it adds declarations or definitions to namespace std or to a namespace within namespace std unless otherwise specified."
While people could read this in various ways, I would say it forbids these kinds of games, although they might work for particular standard libraries.
The standard also gives the reference of what the declarations of the classes of the standard library must be, and all those declarations are in namespace std.
Isn't the standard library allowed to add template parameters with defaults?
template <typename T, typename Allocator, typename _InternalParameter = int> struct vector;
No. The fine details of the standard aren't really important here anyway. In practice there are compilers where we have been able to write well-defined forward declarations for many years and people have found them useful. On other standard libraries, like libc++, forward declarations are hard to write and not advised. Therefore we should support forward declarations where we can, and just include the standard headers where we can't. Chris

On Tue, Feb 22, 2011 at 10:41 AM, Christopher Jefferson <chris@bubblescope.net> wrote:
On 22 Feb 2011, at 13:28, Felipe Magno de Almeida wrote:
[snip]
Isn't the standard library allowed to add template parameters with defaults?
template <typename T, typename Allocator, typename _InternalParameter = int> struct vector;
No.
It seems Robert Steward agrees wit this.
The fine details of the standard aren't really important here anyway. In practice there are compilers where we have been able to write well-defined forward declarations for many years and people have found them useful. On other standard libraries, like libc++, forward declarations are hard to write and not advised.
Therefore we should support forward declarations where we can, and just include the standard headers where we can't.
It might be useful, but it is undefined behavior. I would hope boost would depend as little as possible on undefined behavior.
Chris
Regards, -- Felipe Magno de Almeida
participants (13)
-
Christian Holmquist
-
Christopher Jefferson
-
Daniel James
-
Felipe Magno de Almeida
-
Howard Hinnant
-
Ilya Sokolov
-
Ion Gaztañaga
-
Ivan Le Lann
-
John Maddock
-
Loïc Joly
-
Mathias Gaunard
-
Sebastian Redl
-
Stewart, Robert