[Config] Support for switching between std:: and boost:: equivalents.
There is a pull-request for Config to provide support for switching between boost:: and std:: library equivalents: https://github.com/boostorg/config/pull/63 My questions are: * Is this the right approach? And, * Is Boost.Config the right place for it? Thanks for your comments, John.
On 6/5/2015 3:41 AM, John Maddock wrote:
There is a pull-request for Config to provide support for switching between boost:: and std:: library equivalents: https://github.com/boostorg/config/pull/63
My questions are:
* Is this the right approach? And, * Is Boost.Config the right place for it?
Thanks for your comments, John.
That is my pull request so I will comment now that you have so
graciously provided a forum for my idea.
I don't know what "the right approach" would be but this is one approach
that does work easily, following the documentation I have written about
it and added to the Boost.config documentation.
I have written and added tests for all the Boost libraries involved
which have a C++ standard version which may be interoperably used
instead of the Boost version in code. These tests I would add as PRs to
the particular libraries once this config PR is pushed to 'develop'. The
tests are largely proof of concept tests that show that code does work.
The tests are not meant to be extensive tests for each library's
functionality.
I have also used the code successfully in this PR for a library I am
developing.
It is very easy to use. For library 'XXX':
1) Just include the particular Boost.config header provided for a
particular interoperable library XXX:
#include
On 05 June 2015 10:30, Edward Diener wrote:
On 6/5/2015 3:41 AM, John Maddock wrote:
There is a pull-request for Config to provide support for switching between boost:: and std:: library equivalents: https://github.com/boostorg/config/pull/63
My questions are:
* Is this the right approach? And, * Is Boost.Config the right place for it?
Thanks for your comments, John.
That is my pull request so I will comment now that you have so graciously provided a forum for my idea.
I don't know what "the right approach" would be but this is one approach that does work easily, following the documentation I have written about it and added to the Boost.config documentation.
[snip good detection/reporting macros stuff]
3) In code for that library's functionality use the namespace macro provided for accessing the library's functionality:
BOOST_CPP_XXX_NS::some_functionality etc.
It would be useful to compare the BOOST_CPP_XXX_NS macro approach to providing a namespace with using declarations. I use 'bst'. One advantage is flexibility to adapt the mapping where necessary, e.g. while Boost placeholders were in boost, but std::placeholders. Best regards, Gareth ************************************************************************ The information contained in this message or any of its attachments may be confidential and is intended for the exclusive use of the addressee(s). Any disclosure, reproduction, distribution or other dissemination or use of this communication is strictly prohibited without the express permission of the sender. The views expressed in this email are those of the individual and not necessarily those of Sony or Sony affiliated companies. Sony email is for business use only. This email and any response may be monitored by Sony to be in compliance with Sony's global policies and standards
On 6/5/2015 6:15 AM, Sylvester-Bradley, Gareth wrote:
On 05 June 2015 10:30, Edward Diener wrote:
On 6/5/2015 3:41 AM, John Maddock wrote:
There is a pull-request for Config to provide support for switching between boost:: and std:: library equivalents: https://github.com/boostorg/config/pull/63
My questions are:
* Is this the right approach? And, * Is Boost.Config the right place for it?
Thanks for your comments, John.
That is my pull request so I will comment now that you have so graciously provided a forum for my idea.
I don't know what "the right approach" would be but this is one approach that does work easily, following the documentation I have written about it and added to the Boost.config documentation.
[snip good detection/reporting macros stuff]
3) In code for that library's functionality use the namespace macro provided for accessing the library's functionality:
BOOST_CPP_XXX_NS::some_functionality etc.
It would be useful to compare the BOOST_CPP_XXX_NS macro approach to providing a namespace with using declarations. I use 'bst'.
You could just as easily write: using namespace BOOST_CPP_XXX_NS;
One advantage is flexibility to adapt the mapping where necessary, e.g. while Boost placeholders were in boost, but std::placeholders.
On June 5, 2015 5:30:03 AM EDT, Edward Diener
On 6/5/2015 3:41 AM, John Maddock wrote:
There is a pull-request for Config to provide support for switching between boost:: and std:: library equivalents: https://github.com/boostorg/config/pull/63
My questions are:
* Is this the right approach? And, * Is Boost.Config the right place for it?
I don't know what "the right approach" would be but this is one approach that does work easily.
It does seem like a reasonable approach overall. It's relatively simple and doesn't try to hide much. I can't think of a better place for this than Config.
It is very easy to use. For library 'XXX':
1) Just include the particular Boost.config header provided for a particular interoperable library XXX:
#include
I noticed in your PR that you also provide a header to get all such headers at once. I wonder whether the individual headers are really that useful. You could keep the implementation you have, but just document the one header.
2) Include that library's main header file using the macro provided for that library:
#include BOOST_CPP_XXX_HDR
Why do you have "CPP" in that name? BOOST_XXX_HDR would seem sufficient. I also would suggest using HEADER rather than HDR.
3) In code for that library's functionality use the namespace macro provided for accessing the library's functionality: BOOST_CPP_XXX_NS::some_functionality etc.
Why do you have "CPP" in that name? BOOST_XXX_NS would seem sufficient.
If you need to do anything different depending on whether you are using the C++ standard version of the library or the Boost version of the library you can test the BOOST_CPP_HAS_XXX macro, which is 1 for the C++ standard version existing in the compiler implementation and is 0 for only the Boost version existing in the compiler implementation.
That macro would seem better named, BOOST_HAS_STD_XXX our BOOST_XXX_IS_STD. (The latter is more consistent with my earlier suggestions.) ___ Rob (Sent from my portable computation engine)
On 6/5/2015 10:00 AM, Rob Stewart wrote:
On June 5, 2015 5:30:03 AM EDT, Edward Diener
wrote: On 6/5/2015 3:41 AM, John Maddock wrote:
There is a pull-request for Config to provide support for switching between boost:: and std:: library equivalents: https://github.com/boostorg/config/pull/63
My questions are:
* Is this the right approach? And, * Is Boost.Config the right place for it?
I don't know what "the right approach" would be but this is one approach that does work easily.
It does seem like a reasonable approach overall. It's relatively simple and doesn't try to hide much.
I can't think of a better place for this than Config.
It is very easy to use. For library 'XXX':
1) Just include the particular Boost.config header provided for a particular interoperable library XXX:
#include
I noticed in your PR that you also provide a header to get all such headers at once. I wonder whether the individual headers are really that useful. You could keep the implementation you have, but just document the one header.
The one header is documented. I have the individual headers to avoid flooding the macro namespaces with lots of macros you are not going to use.
2) Include that library's main header file using the macro provided for that library:
#include BOOST_CPP_XXX_HDR
Why do you have "CPP" in that name? BOOST_XXX_HDR would seem sufficient. I also would suggest using HEADER rather than HDR.
I like to avoid macro name clashes, Having a common prefix, such as CPP, tends to do that. As far as the more verbose HEADER instead of the shorter HDR that's fine with me if others like that instead. I could even change BOOST_CPP_XXX_NS to BOOST_CPP_XXX_NAMESPACE and have everybody type out the fully explicit names.
3) In code for that library's functionality use the namespace macro provided for accessing the library's functionality: BOOST_CPP_XXX_NS::some_functionality etc.
Why do you have "CPP" in that name? BOOST_XXX_NS would seem sufficient.
If you need to do anything different depending on whether you are using the C++ standard version of the library or the Boost version of the library you can test the BOOST_CPP_HAS_XXX macro, which is 1 for the C++ standard version existing in the compiler implementation and is 0 for only the Boost version existing in the compiler implementation.
That macro would seem better named, BOOST_HAS_STD_XXX our BOOST_XXX_IS_STD. (The latter is more consistent with my earlier suggestions.)
Again I like distinct macro names so BOOST_CPP_something seems right, but your other suggestions, as BOOST_CPP_HAS_STD_XXX or BOOST_CPP_XXX_IS_STD, are fine. Please realize that all macros are in a global namespace with everything and avoiding macro name clashes in any TU is of paramount importance.
On June 5, 2015 10:42:50 AM EDT, Edward Diener
On June 5, 2015 5:30:03 AM EDT, Edward Diener
wrote: It is very easy to use. For library 'XXX':
1) Just include the particular Boost.config header provided for a particular interoperable library XXX:
#include
I noticed in your PR that you also provide a header to get all such
On 6/5/2015 10:00 AM, Rob Stewart wrote: headers at once. I wonder whether the individual headers are really that useful. You could keep the implementation you have, but just document the one header.
The one header is documented. I have the individual headers to avoid flooding the macro namespaces with lots of macros you are not going to use.
I know you documented the everything header. I was suggesting that you not document or mention the others. I don't think the flooding issue you mention is significant. The macro names are reasonably unique and I don't think there are so many that you need worry about defining them all.
2) Include that library's main header file using the macro provided for that library:
#include BOOST_CPP_XXX_HDR
Why do you have "CPP" in that name? BOOST_XXX_HDR would seem sufficient. I also would suggest using HEADER rather than HDR.
I like to avoid macro name clashes, Having a common prefix, such as CPP, tends to do that.
I understand the concern, but I don't think BOOST_ATOMIC_HEADER, BOOST_ATOMIC_NAMESPACE, BOOST_ATOMIC_IS_STD, etc. would be likely to clash.
I could even change BOOST_CPP_XXX_NS to BOOST_CPP_XXX_NAMESPACE and have everybody type out the fully explicit names.
HEADER won't appear very often, so I thought spelling it out would be fine. The namespace macro might be used more often, so I didn't suggest expanding it. OTOH, the longer name can be mitigated by a namespace alias. ___ Rob (Sent from my portable computation engine)
On 6/5/2015 8:14 PM, Rob Stewart wrote:
On June 5, 2015 10:42:50 AM EDT, Edward Diener
wrote: On June 5, 2015 5:30:03 AM EDT, Edward Diener
wrote: It is very easy to use. For library 'XXX':
1) Just include the particular Boost.config header provided for a particular interoperable library XXX:
#include
I noticed in your PR that you also provide a header to get all such
On 6/5/2015 10:00 AM, Rob Stewart wrote: headers at once. I wonder whether the individual headers are really that useful. You could keep the implementation you have, but just document the one header.
The one header is documented. I have the individual headers to avoid flooding the macro namespaces with lots of macros you are not going to use.
I know you documented the everything header. I was suggesting that you not document or mention the others.
I don't think the flooding issue you mention is significant. The macro names are reasonably unique and I don't think there are so many that you need worry about defining them all.
I think giving people choices is better than not doing so. Why bring in what isn't needed for any give TU ?
2) Include that library's main header file using the macro provided for that library:
#include BOOST_CPP_XXX_HDR
Why do you have "CPP" in that name? BOOST_XXX_HDR would seem sufficient. I also would suggest using HEADER rather than HDR.
I like to avoid macro name clashes, Having a common prefix, such as CPP, tends to do that.
I understand the concern, but I don't think BOOST_ATOMIC_HEADER, BOOST_ATOMIC_NAMESPACE, BOOST_ATOMIC_IS_STD, etc. would be likely to clash.
Actually I do, and I think you are wrong. It is customary for Boost libraries which have macros to name them starting with BOOST_XXX_ where XXX is the library name. Why should I worry about potential clashes by following the exacts same convention for my macros. OTOH I do like your suggestion about changing the name of the BOOST_CPP_HAS_XXX macros to something like BOOST_CPP_XXX_IS_STD, or better yet BOOST_CPP_XXX_USES_STD_LIB, as being much more descriptive even if less terse.
I could even change BOOST_CPP_XXX_NS to BOOST_CPP_XXX_NAMESPACE and have everybody type out the fully explicit names.
HEADER won't appear very often, so I thought spelling it out would be fine. The namespace macro might be used more often, so I didn't suggest expanding it. OTOH, the longer name can be mitigated by a namespace alias.
OK, that seems reasonable. the BOOST_CPP_XXX_HEADER would only be used once each TU so I agree with you on that. No need for the HDR abbreviation. I want to wait until all discussion of the macros are complete before I implement macro naming changes, but I do appreciate your suggestions.
On Friday 05 June 2015 20:14:08 Rob Stewart wrote:
On June 5, 2015 10:42:50 AM EDT, Edward Diener
wrote: The one header is documented. I have the individual headers to avoid flooding the macro namespaces with lots of macros you are not going to use.
I know you documented the everything header. I was suggesting that you not document or mention the others.
If those headers are public, they have to be documented. FWIW, I'm more interested in the individual headers and not the include-all one.
I like to avoid macro name clashes, Having a common prefix, such as CPP, tends to do that.
I understand the concern, but I don't think BOOST_ATOMIC_HEADER, BOOST_ATOMIC_NAMESPACE, BOOST_ATOMIC_IS_STD, etc. would be likely to clash.
Those names are in the namespace of Boost.Atomic by the current conventions. They may not be used now, but can be used later. Please, don't do it.
On June 6, 2015 5:07:40 AM EDT, Andrey Semashev
On Friday 05 June 2015 20:14:08 Rob Stewart wrote:
I don't think BOOST_ATOMIC_HEADER, BOOST_ATOMIC_NAMESPACE, BOOST_ATOMIC_IS_STD, etc. would be likely to
clash.
Those names are in the namespace of Boost.Atomic by the current conventions. They may not be used now, but can be used later. Please, don't do it.
Each of the affected libraries can consider this set of names as belonging to the library despite being defined by Config. They also don't seem likely, though I haven't checked, to be used currently. For those reasons I don't see the problem. The proposed unique tag, CPP, is meaningless. It may create a namespace not already used, but it also doesn't relate to the function of the macros. Since Boost.Config doesn't have its own tag, it seemed reasonable that these not have a tag, which makes them extensions of the affected libraries' macros. Whether there is a tag, or even if the tag is CPP, the macros appear useful. ___ Rob (Sent from my portable computation engine)
On Saturday 06 June 2015 06:12:21 Rob Stewart wrote:
On June 6, 2015 5:07:40 AM EDT, Andrey Semashev
wrote: On Friday 05 June 2015 20:14:08 Rob Stewart wrote:
I don't think BOOST_ATOMIC_HEADER, BOOST_ATOMIC_NAMESPACE, BOOST_ATOMIC_IS_STD, etc. would be likely to
clash.
Those names are in the namespace of Boost.Atomic by the current conventions. They may not be used now, but can be used later. Please, don't do it.
Each of the affected libraries can consider this set of names as belonging to the library despite being defined by Config. They also don't seem likely, though I haven't checked, to be used currently. For those reasons I don't see the problem.
I disagree. The macros, as they are currently proposed, are part of Boost.Config. Otherwise they should be proposed to each library separately and then, yes, they would have names according to each library's namespace. Whether the libraries are used or not is irrelevant, the namespaces are still reserved.
The proposed unique tag, CPP, is meaningless. It may create a namespace not already used, but it also doesn't relate to the function of the macros. Since Boost.Config doesn't have its own tag, it seemed reasonable that these not have a tag, which makes them extensions of the affected libraries' macros.
I suggested to change the tag to CXX in the pull request, to follow the current practice in Boost.Config. It seems a reasonable tag to me as these macros deal with C++ implementation capabilities (or rather STL capabilities - which could be used as an alternative tag). I don't mind if a different tag is chosen. I would just like the names to be still organized and not clash with other libraries namespaces.
On 6/6/2015 5:07 AM, Andrey Semashev wrote:
On Friday 05 June 2015 20:14:08 Rob Stewart wrote:
On June 5, 2015 10:42:50 AM EDT, Edward Diener
wrote: The one header is documented. I have the individual headers to avoid flooding the macro namespaces with lots of macros you are not going to use.
I know you documented the everything header. I was suggesting that you not document or mention the others.
If those headers are public, they have to be documented. FWIW, I'm more interested in the individual headers and not the include-all one.
They are "public" and they are documented. The general header is for convenience and to give uses of the macro system a choice.
I like to avoid macro name clashes, Having a common prefix, such as CPP, tends to do that.
I understand the concern, but I don't think BOOST_ATOMIC_HEADER, BOOST_ATOMIC_NAMESPACE, BOOST_ATOMIC_IS_STD, etc. would be likely to clash.
Those names are in the namespace of Boost.Atomic by the current conventions. They may not be used now, but can be used later. Please, don't do it.
I agree with you and that is the reason for using a mnemonic for each macro. I am not against changing from BOOST_CPP_ to BOOST_CXX_. I just want to make sure before I do that no other Boost library or set of macros is using BOOST_CXX_.
On 6/5/2015 10:11 AM, Robert Ramey wrote:
On 6/5/15 2:30 AM, Edward Diener wrote:
Questions, concerns etc are welcome.
Is there an easy way to see the html verions of this?
https://htmlpreview.github.io/?https://github.com/eldiener/config/blob/devel...
On Friday 05 June 2015 05:30:03 Edward Diener wrote:
On 6/5/2015 3:41 AM, John Maddock wrote:
There is a pull-request for Config to provide support for switching between boost:: and std:: library equivalents: https://github.com/boostorg/config/pull/63
My questions are:
* Is this the right approach? And, * Is Boost.Config the right place for it?
Thanks for your comments, John.
That is my pull request so I will comment now that you have so graciously provided a forum for my idea.
I don't know what "the right approach" would be but this is one approach that does work easily, following the documentation I have written about it and added to the Boost.config documentation.
I have written and added tests for all the Boost libraries involved which have a C++ standard version which may be interoperably used instead of the Boost version in code. These tests I would add as PRs to the particular libraries once this config PR is pushed to 'develop'. The tests are largely proof of concept tests that show that code does work. The tests are not meant to be extensive tests for each library's functionality.
I have also used the code successfully in this PR for a library I am developing.
It is very easy to use. For library 'XXX':
1) Just include the particular Boost.config header provided for a particular interoperable library XXX:
#include
2) Include that library's main header file using the macro provided for that library:
#include BOOST_CPP_XXX_HDR
3) In code for that library's functionality use the namespace macro provided for accessing the library's functionality:
BOOST_CPP_XXX_NS::some_functionality etc.
In general, this might be useful in some constrained contexts, but I have a few concerns: 1. What if the Boost version requires linking with a built library? These headers won't be able to hide that. 2. I'm worried if these tools will be used in Boost libraries in a way that affects library API/ABI. What if one library uses these tools and the other doesn't - will these libraries be able to interoperate? Or is it a user's problem? There is also the possibility that Boost is built in C++03 mode and the user builds his code in C++11. I think this will be most apparent with utilities like shared_ptr and function, which are often present in the interfaces.
If you need to do anything different depending on whether you are using the C++ standard version of the library or the Boost version of the library you can test the BOOST_CPP_HAS_XXX macro, which is 1 for the C++ standard version existing in the compiler implementation and is 0 for only the Boost version existing in the compiler implementation.
That's it for any given library supported. You are using the C++ standard version of the library if it exists in the compiler implementation or the Boost version of the library if it does not exists in the compiler implementation.
The Boost implementations supported are:
array atomic bind chrono function hash mem_fn random ratio reg/creg regex shared_ptr thread tuple type_index type_traits unordered_map unordered_multimap unordered_set unordered_multiset
If I have missed any Boost libraries which have a close C++ standard equivalent just tell me and I will add it with some added tests for that particular library.
If you have thread you could also add mutex, condition_variable and locks.
On 6/5/2015 3:37 PM, Andrey Semashev wrote:
On Friday 05 June 2015 05:30:03 Edward Diener wrote:
On 6/5/2015 3:41 AM, John Maddock wrote:
There is a pull-request for Config to provide support for switching between boost:: and std:: library equivalents: https://github.com/boostorg/config/pull/63
My questions are:
* Is this the right approach? And, * Is Boost.Config the right place for it?
Thanks for your comments, John.
That is my pull request so I will comment now that you have so graciously provided a forum for my idea.
I don't know what "the right approach" would be but this is one approach that does work easily, following the documentation I have written about it and added to the Boost.config documentation.
I have written and added tests for all the Boost libraries involved which have a C++ standard version which may be interoperably used instead of the Boost version in code. These tests I would add as PRs to the particular libraries once this config PR is pushed to 'develop'. The tests are largely proof of concept tests that show that code does work. The tests are not meant to be extensive tests for each library's functionality.
I have also used the code successfully in this PR for a library I am developing.
It is very easy to use. For library 'XXX':
1) Just include the particular Boost.config header provided for a particular interoperable library XXX:
#include
2) Include that library's main header file using the macro provided for that library:
#include BOOST_CPP_XXX_HDR
3) In code for that library's functionality use the namespace macro provided for accessing the library's functionality:
BOOST_CPP_XXX_NS::some_functionality etc.
In general, this might be useful in some constrained contexts, but I have a few concerns:
1. What if the Boost version requires linking with a built library? These headers won't be able to hide that.
You are correct. But what are the issues about linking to a Boost library which needs to be addressed as you see it ? Notice that anything necessary to linking to a Boost library can be figured out macro-wise for a given library by first currently testing BOOST_CPP_HAS_XXX for 0 to determine that it is the Boost library which will be used. Of course some other BOOST_CPP_XXX macro would need to be added to specify whether the Boost library needs to be linked or not. So if there is anything which could be automated as part of the source code to automate linking I should be able to automatically configure it using macros also. As an expansion of the basic set of macros which are offered for each library, if the solution to linking is a generic solution I do not mind adding it in. But let's first identify the problem before we can identify any possible generic solution.
2. I'm worried if these tools will be used in Boost libraries in a way that affects library API/ABI. What if one library uses these tools and the other doesn't - will these libraries be able to interoperate? Or is it a user's problem? There is also the possibility that Boost is built in C++03 mode and the user builds his code in C++11. I think this will be most apparent with utilities like shared_ptr and function, which are often present in the interfaces.
Its no different from some Boost library using the C++ standard version of, let's say, std::function because it is available and another library using boost::function. Is API/ABI compatibility affected ? If so that has to be taken into account if you use those libraries internally. Suppose library X is compiled using C++11 mode and your own library Y, which uses library X as a dependency, is compiled without C++11 mode. Again those factors of interoperability between the libraries must be taken into account. Using my macros is not going to change any of that, and my macro system cannot solve that problem, or make it more or less than if the macro system I propose were not used at all. So while I understand your worries I think it is a general one as more Boost libraries use C++ standard equivalents of Boost libraries as dependencies while other current Boost libraries stay with their Boost library equivalents as dependencies. My macro system, while making it easier to generically use one or the other, just brings out a problem that would have happened anyway. The only way to stop this problem is to establish rigid rules of what each Boost library must use, and we can't of course do that.
If you need to do anything different depending on whether you are using the C++ standard version of the library or the Boost version of the library you can test the BOOST_CPP_HAS_XXX macro, which is 1 for the C++ standard version existing in the compiler implementation and is 0 for only the Boost version existing in the compiler implementation.
That's it for any given library supported. You are using the C++ standard version of the library if it exists in the compiler implementation or the Boost version of the library if it does not exists in the compiler implementation.
The Boost implementations supported are:
array atomic bind chrono function hash mem_fn random ratio reg/creg regex shared_ptr thread tuple type_index type_traits unordered_map unordered_multimap unordered_set unordered_multiset
If I have missed any Boost libraries which have a close C++ standard equivalent just tell me and I will add it with some added tests for that particular library.
If you have thread you could also add mutex, condition_variable and locks.
OK, I will look into this. If any of them are in different headers and/or namespaces than 'thread' they will need there own set of HDR, NS, and HAS macros and initial boost/config/cpp/xxx.hpp header file to be included. Thanks for pointing these other implementations out ! I expected I might have missed a few.
Edward Diener wrote:
Suppose library X is compiled using C++11 mode and your own library Y, which uses library X as a dependency, is compiled without C++11 mode. Again those factors of interoperability between the libraries must be taken into account. Using my macros is not going to change any of that, ...
No, but one could argue that the existence of your macros in Boost.Config is going to encourage people to use them and hence make this situation more likely.
On 6/5/2015 5:20 PM, Peter Dimov wrote:
Edward Diener wrote:
Suppose library X is compiled using C++11 mode and your own library Y, which uses library X as a dependency, is compiled without C++11 mode. Again those factors of interoperability between the libraries must be taken into account. Using my macros is not going to change any of that, ...
No, but one could argue that the existence of your macros in Boost.Config is going to encourage people to use them and hence make this situation more likely.
I agree but incorporating C++11 libraries or using C++11 language features in code is inevitable anyway. If my macros make it easier to do the former I view that as a success. I certainly feel that making easier to move forward toward C++11/C++14/C++17 should be one of the goals of Boost, rather than holding people back from doing so. I know that in a library on which I am working if the corresponding C++ standard equivalent libraries to certain Boost libraries are available I want to use them. There are situations where you might want to stick to the Boost version of a library when a C++ standard equivalent is available, but that's easy to do by just ignoring my macro system. Similarly you can use my macro system so that if you only want to use the C++ standard equivalent version of a Boost library you can easily create a preprocessor #error if it is not available.
On Friday 05 June 2015 17:05:08 Edward Diener wrote:
On 6/5/2015 3:37 PM, Andrey Semashev wrote:
1. What if the Boost version requires linking with a built library? These headers won't be able to hide that.
You are correct. But what are the issues about linking to a Boost library which needs to be addressed as you see it ?
Notice that anything necessary to linking to a Boost library can be figured out macro-wise for a given library by first currently testing BOOST_CPP_HAS_XXX for 0 to determine that it is the Boost library which will be used. Of course some other BOOST_CPP_XXX macro would need to be added to specify whether the Boost library needs to be linked or not. So if there is anything which could be automated as part of the source code to automate linking I should be able to automatically configure it using macros also. As an expansion of the basic set of macros which are offered for each library, if the solution to linking is a generic solution I do not mind adding it in. But let's first identify the problem before we can identify any possible generic solution.
In general, you won't get away with just macros, as autolinking is only present in MSVC & friends. This would also affect build system scripts. Suppose I'm a (Boost) library writer; the library has a compiled part and I'm writing a Makefile/Jamfile. If I'm using these macros, I still have to know when to link and when not to link with Boost libs. This can be rather tricky as not only compiler versions should be checked but also their options; and it also needs to be in sync with Boost.Config. The same happens when I'm a user of a (Boost) library that uses these macros, only it becomes more difficult to be in sync with Boost.Config. My point is that since these macros don't actually abstract me away from the configuration, why would I use them? Arguably, this problem goes away if the macros only handle components which are header-only in Boost.
2. I'm worried if these tools will be used in Boost libraries in a way that affects library API/ABI. What if one library uses these tools and the other doesn't - will these libraries be able to interoperate? Or is it a user's problem? There is also the possibility that Boost is built in C++03 mode and the user builds his code in C++11. I think this will be most apparent with utilities like shared_ptr and function, which are often present in the interfaces.
Its no different from some Boost library using the C++ standard version of, let's say, std::function because it is available and another library using boost::function. Is API/ABI compatibility affected ? If so that has to be taken into account if you use those libraries internally. Suppose library X is compiled using C++11 mode and your own library Y, which uses library X as a dependency, is compiled without C++11 mode.
It's more likely that Boost is compiled in one mode and distributed in a standard package (say, with a Linux distro) and I'm building my app locally with that Boost. Most Linux distros build Boost with default compiler options which means C++03. If these macros affect Boost libraries ABI I will no longer be able to build my app in C++11 mode.
Again those factors of interoperability between the libraries must be taken into account. Using my macros is not going to change any of that, and my macro system cannot solve that problem, or make it more or less than if the macro system I propose were not used at all.
As Peter noted, having these macros in Boost.Config can be seen as encouragement to use. And when used improperly they can cause real problems. So far I'm seeing these macros only applicable under the following conditions: a) the macros can be used in header-only libraries or concealed in the compiled part of the library without exposing it to API/ABI, and b) only when these macros allow to switch between STL and header-only Boost alternatives (not compiled ones). I'm not sure how to enforce these restrictions and I'm not sure adding them without doing something about their dangerous use is a good idea. Sorry if I'm not being helpful here.
On 6/5/2015 6:35 PM, Andrey Semashev wrote:
On Friday 05 June 2015 17:05:08 Edward Diener wrote:
On 6/5/2015 3:37 PM, Andrey Semashev wrote:
1. What if the Boost version requires linking with a built library? These headers won't be able to hide that.
You are correct. But what are the issues about linking to a Boost library which needs to be addressed as you see it ?
Notice that anything necessary to linking to a Boost library can be figured out macro-wise for a given library by first currently testing BOOST_CPP_HAS_XXX for 0 to determine that it is the Boost library which will be used. Of course some other BOOST_CPP_XXX macro would need to be added to specify whether the Boost library needs to be linked or not. So if there is anything which could be automated as part of the source code to automate linking I should be able to automatically configure it using macros also. As an expansion of the basic set of macros which are offered for each library, if the solution to linking is a generic solution I do not mind adding it in. But let's first identify the problem before we can identify any possible generic solution.
In general, you won't get away with just macros, as autolinking is only present in MSVC & friends. This would also affect build system scripts.
Suppose I'm a (Boost) library writer; the library has a compiled part and I'm writing a Makefile/Jamfile. If I'm using these macros, I still have to know when to link and when not to link with Boost libs. This can be rather tricky as not only compiler versions should be checked but also their options; and it also needs to be in sync with Boost.Config. The same happens when I'm a user of a (Boost) library that uses these macros, only it becomes more difficult to be in sync with Boost.Config. My point is that since these macros don't actually abstract me away from the configuration, why would I use them?
They abstract you away from having to write complicated code which caters to whether or not a C++ standard library equivalent to a Boost library is available or not. They don't relieve the responsibility of a built library from naming itself in such a way that those linking with the library can do so successfully if auto-linking is not available.
Arguably, this problem goes away if the macros only handle components which are header-only in Boost.
2. I'm worried if these tools will be used in Boost libraries in a way that affects library API/ABI. What if one library uses these tools and the other doesn't - will these libraries be able to interoperate? Or is it a user's problem? There is also the possibility that Boost is built in C++03 mode and the user builds his code in C++11. I think this will be most apparent with utilities like shared_ptr and function, which are often present in the interfaces.
The problem goes beyond the use of my macro system. Are we going to give library developers the choice of whether they can use the C++ standard library equivalent to a Boost library or not ? Please see my answer to this at the emnd of my response.
Its no different from some Boost library using the C++ standard version of, let's say, std::function because it is available and another library using boost::function. Is API/ABI compatibility affected ? If so that has to be taken into account if you use those libraries internally. Suppose library X is compiled using C++11 mode and your own library Y, which uses library X as a dependency, is compiled without C++11 mode.
It's more likely that Boost is compiled in one mode and distributed in a standard package (say, with a Linux distro) and I'm building my app locally with that Boost. Most Linux distros build Boost with default compiler options which means C++03. If these macros affect Boost libraries ABI I will no longer be able to build my app in C++11 mode.
The macros don't determine the mode; compiler options do that. I believe Boost is going to have to work out anyway, if it has not already done so, a difference in final naming between a library built with or without C++11/C++14/C++17 support if that library supports building in more than one C++ mode.
Again those factors of interoperability between the libraries must be taken into account. Using my macros is not going to change any of that, and my macro system cannot solve that problem, or make it more or less than if the macro system I propose were not used at all.
As Peter noted, having these macros in Boost.Config can be seen as encouragement to use. And when used improperly they can cause real problems.
So far I'm seeing these macros only applicable under the following conditions:
a) the macros can be used in header-only libraries or concealed in the compiled part of the library without exposing it to API/ABI, and
b) only when these macros allow to switch between STL and header-only Boost alternatives (not compiled ones).
I'm not sure how to enforce these restrictions and I'm not sure adding them without doing something about their dangerous use is a good idea. Sorry if I'm not being helpful here.
Arguing that a facility is bad because it makes it easier to use either a C++ standard library equivalent to a Boost library or the Boost library itself, as you and Peter have done, is counterproductive IMO. The same problems would exist as soon as anyone decides to use one or the other in their code even without my macros. I can't view it as being better to only use Boost libraries in Boost library code simply because it creates a single variant of a library. Eventually people will become tired of not having the ability to use C++ standard library equivalents in Boost code, and this will become more so if Boost moves to a more modular distribution system. What will you tell people ? That they must hard-code whether to use a Boost library or a C++ standard equivalent library in their code ? And if the C++ standard library equivalent is not available their library must be unusable in that environment ? I don't think Boost is going to get very far in that direction. I acknowledge the concerns which you have with a built library which can be compiled in different C++ modes. My point of view is different in that Boost has to face the fact that for any given library XXX it may want to use a Boost library in one C++ mode, presumably C++03, and the C++ standard equivalent of that Boost library in another C++ mode, presumably C++11 or above. For this different naming conventions for such a dual mode ( or more ) built library has to be created to accomodate the situation. Either that or the library itself must be treated under a different name for each mode in which it can be built, but that's not a problem which my macro system itself can solve.
On Friday 05 June 2015 21:07:20 Edward Diener wrote:
On 6/5/2015 6:35 PM, Andrey Semashev wrote:
In general, you won't get away with just macros, as autolinking is only present in MSVC & friends. This would also affect build system scripts.
Suppose I'm a (Boost) library writer; the library has a compiled part and I'm writing a Makefile/Jamfile. If I'm using these macros, I still have to know when to link and when not to link with Boost libs. This can be rather tricky as not only compiler versions should be checked but also their options; and it also needs to be in sync with Boost.Config. The same happens when I'm a user of a (Boost) library that uses these macros, only it becomes more difficult to be in sync with Boost.Config. My point is that since these macros don't actually abstract me away from the configuration, why would I use them?
They abstract you away from having to write complicated code which caters to whether or not a C++ standard library equivalent to a Boost library is available or not. They don't relieve the responsibility of a built library from naming itself in such a way that those linking with the library can do so successfully if auto-linking is not available.
I think you missed my point above. It's not about naming the library, its about the solution being incomplete to the point when you are not saved much by using these macros. I've looked at the headers, and a similar code in a few Boost libraries that does the same - there's nothing complicated there. I believe that implementing a similar logic in a Jamfile to link with Boost libraries only when needed would be much more difficult and error prone.
The problem goes beyond the use of my macro system. Are we going to give library developers the choice of whether they can use the C++ standard library equivalent to a Boost library or not ?
My current view on this is if you're writing a C++11 library it's fairly logical for you to use STL11. No macros are needed for that. If you aim for C++03 compatibility, you should use STL03 and Boost where STL lacks something. Admittedly, this approach still has the library interoperability problem but at least your API and ABI are stable and do not depend on compiler options. I realize that someone might want to switch to C++11 components when available, for example, to reduce dependencies on other Boost libraries. But I believe this should only be done in a way that does not affect API and ABI of the library.
It's more likely that Boost is compiled in one mode and distributed in a standard package (say, with a Linux distro) and I'm building my app locally with that Boost. Most Linux distros build Boost with default compiler options which means C++03. If these macros affect Boost libraries ABI I will no longer be able to build my app in C++11 mode.
The macros don't determine the mode; compiler options do that. I believe Boost is going to have to work out anyway, if it has not already done so, a difference in final naming between a library built with or without C++11/C++14/C++17 support if that library supports building in more than one C++ mode.
I think the current solution is to provide ABI that does not depend on C++ mode. This is what I'm doing in Boost.Log, and AFAIR there was a bugfix in Boost.Filesystem that also followed this direction. I can also remember a fix in Boost.Range that removed the difference in binary layout of iterator_range between release and debug builds - not a C++ mode issue, but similar enough. One may argue that this approach is limiting, and I would agree, but this has worked best for the downstream so far.
Arguing that a facility is bad because it makes it easier to use either a C++ standard library equivalent to a Boost library or the Boost library itself, as you and Peter have done, is counterproductive IMO.
Maybe. That's why I apologized for not being helpful. I understand your argument - after all C++ allows you to shoot yourself in the foot, so do your macros. But unlike C++ they don't make it really difficult. Maybe we just need a documented policy of use of these macros so that they don't get misused. Maybe we need testing, when the library and tests are compiled in different C++ modes. I don't know.
The same problems would exist as soon as anyone decides to use one or the other in their code even without my macros. I can't view it as being better to only use Boost libraries in Boost library code simply because it creates a single variant of a library. Eventually people will become tired of not having the ability to use C++ standard library equivalents in Boost code, and this will become more so if Boost moves to a more modular distribution system. What will you tell people ? That they must hard-code whether to use a Boost library or a C++ standard equivalent library in their code ? And if the C++ standard library equivalent is not available their library must be unusable in that environment ? I don't think Boost is going to get very far in that direction.
Some of these questions I've answered above. I'll just add that developers have always had to find balance between maintainability and usability and I don't think it'll change any time soon. Personally, for my projects I have decided that trying to use STL11 opportunistically doesn't worth the hassle. Even for C++11 projects I still prefer Boost to STL in some cases. But your mileage may wary, of course.
I acknowledge the concerns which you have with a built library which can be compiled in different C++ modes. My point of view is different in that Boost has to face the fact that for any given library XXX it may want to use a Boost library in one C++ mode, presumably C++03, and the C++ standard equivalent of that Boost library in another C++ mode, presumably C++11 or above. For this different naming conventions for such a dual mode ( or more ) built library has to be created to accomodate the situation. Either that or the library itself must be treated under a different name for each mode in which it can be built, but that's not a problem which my macro system itself can solve.
Producing different library names for different C++ modes has been discussed before but I don't quite remember the outcome of that discussion. Clearly, it has not been implemented. By the way, Boost is not the only project that attempts to maintain stable ABI regardless of the C++ mode. libstdc++ is also doing that, for example.
On 6/6/2015 8:26 AM, Andrey Semashev wrote:
On Friday 05 June 2015 21:07:20 Edward Diener wrote:
On 6/5/2015 6:35 PM, Andrey Semashev wrote:
In general, you won't get away with just macros, as autolinking is only present in MSVC & friends. This would also affect build system scripts.
Suppose I'm a (Boost) library writer; the library has a compiled part and I'm writing a Makefile/Jamfile. If I'm using these macros, I still have to know when to link and when not to link with Boost libs. This can be rather tricky as not only compiler versions should be checked but also their options; and it also needs to be in sync with Boost.Config. The same happens when I'm a user of a (Boost) library that uses these macros, only it becomes more difficult to be in sync with Boost.Config. My point is that since these macros don't actually abstract me away from the configuration, why would I use them?
They abstract you away from having to write complicated code which caters to whether or not a C++ standard library equivalent to a Boost library is available or not. They don't relieve the responsibility of a built library from naming itself in such a way that those linking with the library can do so successfully if auto-linking is not available.
I think you missed my point above. It's not about naming the library, its about the solution being incomplete to the point when you are not saved much by using these macros.
I do not understand what sort of completeness you desire.
I've looked at the headers, and a similar code in a few Boost libraries that does the same - there's nothing complicated there.
Absolutely. I invented a general solution so that each Boost library doesn't have to re-invent it. It's meant to be simple.
I believe that implementing a similar logic in a Jamfile to link with Boost libraries only when needed would be much more difficult and error prone.
The problem goes beyond the use of my macro system. Are we going to give library developers the choice of whether they can use the C++ standard library equivalent to a Boost library or not ?
My current view on this is if you're writing a C++11 library it's fairly logical for you to use STL11. No macros are needed for that. If you aim for C++03 compatibility, you should use STL03 and Boost where STL lacks something. Admittedly, this approach still has the library interoperability problem but at least your API and ABI are stable and do not depend on compiler options.
And suppose you want your library to work with either STL11 or STL03 ? Do you just decide that it is not possible so you have to choose one or the other ? That after all is what you are essentially saying a Boost library must do, is it not ? I find that irritating, not because I think the Boost libraries are any worse than their C++ equivalents, but because I see no reason why I should either have dependencies on other Boost libraries when I don't need to or that I have to cut off all end-users of my library compiler implementations if I choose just C++11 mode and STL11.
I realize that someone might want to switch to C++11 components when available, for example, to reduce dependencies on other Boost libraries. But I believe this should only be done in a way that does not affect API and ABI of the library.
It's more likely that Boost is compiled in one mode and distributed in a standard package (say, with a Linux distro) and I'm building my app locally with that Boost. Most Linux distros build Boost with default compiler options which means C++03. If these macros affect Boost libraries ABI I will no longer be able to build my app in C++11 mode.
The macros don't determine the mode; compiler options do that. I believe Boost is going to have to work out anyway, if it has not already done so, a difference in final naming between a library built with or without C++11/C++14/C++17 support if that library supports building in more than one C++ mode.
I think the current solution is to provide ABI that does not depend on C++ mode. This is what I'm doing in Boost.Log, and AFAIR there was a bugfix in Boost.Filesystem that also followed this direction. I can also remember a fix in Boost.Range that removed the difference in binary layout of iterator_range between release and debug builds - not a C++ mode issue, but similar enough. One may argue that this approach is limiting, and I would agree, but this has worked best for the downstream so far.
Arguing that a facility is bad because it makes it easier to use either a C++ standard library equivalent to a Boost library or the Boost library itself, as you and Peter have done, is counterproductive IMO.
Maybe. That's why I apologized for not being helpful.
I understand your argument - after all C++ allows you to shoot yourself in the foot, so do your macros. But unlike C++ they don't make it really difficult. Maybe we just need a documented policy of use of these macros so that they don't get misused. Maybe we need testing, when the library and tests are compiled in different C++ modes. I don't know.
I have developed a series of proof of concept tests for each of the libraries the macro system supports in either C++03 or C++11 mode. I have not tried to add PRs for those tests for each Boost library yet because my macro system is not in Boost.config 'develop' yet, and I don't want failings test for no reason.
The same problems would exist as soon as anyone decides to use one or the other in their code even without my macros. I can't view it as being better to only use Boost libraries in Boost library code simply because it creates a single variant of a library. Eventually people will become tired of not having the ability to use C++ standard library equivalents in Boost code, and this will become more so if Boost moves to a more modular distribution system. What will you tell people ? That they must hard-code whether to use a Boost library or a C++ standard equivalent library in their code ? And if the C++ standard library equivalent is not available their library must be unusable in that environment ? I don't think Boost is going to get very far in that direction.
Some of these questions I've answered above. I'll just add that developers have always had to find balance between maintainability and usability and I don't think it'll change any time soon. Personally, for my projects I have decided that trying to use STL11 opportunistically doesn't worth the hassle. Even for C++11 projects I still prefer Boost to STL in some cases. But your mileage may wary, of course.
I acknowledge the concerns which you have with a built library which can be compiled in different C++ modes. My point of view is different in that Boost has to face the fact that for any given library XXX it may want to use a Boost library in one C++ mode, presumably C++03, and the C++ standard equivalent of that Boost library in another C++ mode, presumably C++11 or above. For this different naming conventions for such a dual mode ( or more ) built library has to be created to accomodate the situation. Either that or the library itself must be treated under a different name for each mode in which it can be built, but that's not a problem which my macro system itself can solve.
Producing different library names for different C++ modes has been discussed before but I don't quite remember the outcome of that discussion. Clearly, it has not been implemented.
Boost has implemented the notion that for libraries being built that the
library name changes depending on whether or not the dynamic RTL or
static RTL of the compiler implementation is being used. Also the
library name changes depending on whether the library itself being built
is a static or shared library. And there are a few more of these name
manipulations which Boost enforces. I am simply arguing that we can come
up with a means for doing the same on demand for C++ modes, not that we
must do the same thing for C++ modes at all times.
Let me give a very simple practical use case and this will illustrate
what I am trying to discuss.
I develop library EDS_LIB and it is a Boost library which must be built
as a library and is not header-only, and my library uses regex in some
interface it exports.
I have a decision to make: do I use Boost.regex and therefore work in
any C++ mode or do I use std::regex and therefore works only in C++11
mode ( which I will assume supports the std::regex library ). Most
people will say to use Boost.regex and be able to support any mode. Fair
enough, but now EDS_LIB depends on Boost regex. If Boost ever goes to a
more modular distribution all distribution of EDS_LIB must also include
Boost regex.
OTOH if I choose C++11 mode the dependency on Boost.regex goes away, but
now you need to compile whatever uses EDS_LIB in C++11 mode else my
library is useless to you.
Now let's suppose, using my macro system, I can distribute my library as
EDS_LIB in C++03 mode or EDS_LIB_C11 in C++11 mode. My exported
interface using regex is:
#include
By the way, Boost is not the only project that attempts to maintain stable ABI regardless of the C++ mode. libstdc++ is also doing that, for example.
How many other library dependencies does libstdc++ have ? Then ask yourself how many other library dependencies does any given Boost library have ? Have I made my point ?
Edward Diener wrote:
Let me give a very simple practical use case and this will illustrate what I am trying to discuss.
I develop library EDS_LIB and it is a Boost library which must be built as a library and is not header-only, and my library uses regex in some interface it exports.
I have a decision to make: do I use Boost.regex and therefore work in any C++ mode or do I use std::regex and therefore works only in C++11 mode ( which I will assume supports the std::regex library ). Most people will say to use Boost.regex and be able to support any mode. Fair enough, but now EDS_LIB depends on Boost regex.
And what is the use case in which you don't have Boost.Regex but do have Boost.Config so that you can use your proposed mechanism? If your library is not part of the Boost distribution, it might make sense for your library to support building without Boost, in which case one would expect your library to not need Boost.Config, wouldn't one? And if your library is part of the Boost distribution, one would expect Boost.Regex to also be present, wouldn't one?
If Boost ever goes to a more modular distribution all distribution of EDS_LIB must also include Boost regex.
Right. But this isn't the case now.
On 6/6/2015 5:05 PM, Peter Dimov wrote:
Edward Diener wrote:
Let me give a very simple practical use case and this will illustrate what I am trying to discuss.
I develop library EDS_LIB and it is a Boost library which must be built as a library and is not header-only, and my library uses regex in some interface it exports.
I have a decision to make: do I use Boost.regex and therefore work in any C++ mode or do I use std::regex and therefore works only in C++11 mode ( which I will assume supports the std::regex library ). Most people will say to use Boost.regex and be able to support any mode. Fair enough, but now EDS_LIB depends on Boost regex.
And what is the use case in which you don't have Boost.Regex but do have Boost.Config so that you can use your proposed mechanism?
That use case does not currently exist. But I am missing your point. The mechanism says that if std::regex exists, use it instead of boost::regex. If std::regex does not exist use boost::regex instead. If I don't have a dependency on boost::regex and std::regex supplies all my module's needs is it not better to use std::regex, so that in a future modular Boost distribution based system I will not have to distribute boost::regex with my library ?
If your library is not part of the Boost distribution, it might make sense for your library to support building without Boost, in which case one would expect your library to not need Boost.Config, wouldn't one?
I can have my macros not be part of Boost.Config but why would I do that ? The macros work to choose either a Boost library or its C++ standard equivalent at compile time. The macros also use what is in Boost.config to make that choice. If the macros are dependent on Boost.Config why should they not be a part of Boost.config ?
And if your library is part of the Boost distribution, one would expect Boost.Regex to also be present, wouldn't one?
Of course. There is some sort of disconnect here, because I can't make out what you are getting at.
If Boost ever goes to a more modular distribution all distribution of EDS_LIB must also include Boost regex.
Right. But this isn't the case now.
Correct. You can say that now my macros don't buy you anything and the right choice is to always use Boost libraries instead of their C++11 standard library equivalents. But of course if you are one of those people who see unneeded dependencies on other Boost libraries as a negative thing, you could argue that cutting down on those dependencies, by using their C++11 standard equivalents when compiling in C++11 mode, is a positive thing. My argument is that if Boost ever goes to a modular Boost distribution system, where a single library, whether built ot header-only, is distributed with its dependencies, you could use my macro system so that you can distribute the library without having to distribute, as in the example, boost::regex with it when the library is going to be used in C++11 mode. And you do that without having to change your code in any way. I can fully understand the viewpoint which says that in our current Boost distribution it does not mean anything to reduce a dependency on Boost libraries when compiled in C++11 mode, since the library is already there in the distribution. For those people, who are probably the vast majority, you simple decide to use the Boost library, even in C++11 mode, and you are done with it, and my macro system is a waste of time and an added complication. My solution is for the future, if and when we distribute Boost libraries independently. Somebody, I forget who, wrote a Boost tool for extracting a library and its dependencies into a sort of mini-distribution. So somebody else is thinking somewhat along the lines I was thinking when I came up with my macro solution, that allowing a single library to be used with its dependencies might be a good thing, and therefore reducing its dependencies without impairing/changing its functionality helps that situation.
Edward Diener wrote:
That use case does not currently exist. But I am missing your point.
That was my point. The use case doesn't exist yet. You were obviously motivated by something to propose the macros, and I was wondering what that something was. Did you actually have a use case, or was that in anticipation of what the future will bring. It appears that it's the latter, in which case, I'm still interested in your anticipated future use case.
The mechanism says that if std::regex exists, use it instead of boost::regex. If std::regex does not exist use boost::regex instead. If I don't have a dependency on boost::regex and std::regex supplies all my module's needs is it not better to use std::regex, so that in a future modular Boost distribution based system I will not have to distribute boost::regex with my library ?
So your anticipated future use case is that you want to create a distribution for your library that contains Boost.Config but does not contain Boost.Regex?
There is some sort of disconnect here, because I can't make out what you are getting at.
You're putting the cart before the horse (Cartesius ante equum, as they say). The modular future hasn't arrived yet and we have no idea what it will be.
Somebody, I forget who, wrote a Boost tool for extracting a library and its dependencies into a sort of mini-distribution.
John Maddock, the tool is called bcp.
On 6/6/2015 7:21 PM, Peter Dimov wrote:
Edward Diener wrote:
That use case does not currently exist. But I am missing your point.
That was my point. The use case doesn't exist yet.
You were obviously motivated by something to propose the macros, and I was wondering what that something was. Did you actually have a use case, or was that in anticipation of what the future will bring.
It appears that it's the latter, in which case, I'm still interested in your anticipated future use case.
The use case is that I support/use the C++ standard library equivalents to Boost libraries in C++11 mode and I support/use the Boost libraries in C++03 mode. That should make it easier for my library's code to work with what the user of my library will most likely use in his own code. I design a library which, let's say, takes a regex object as parameter to some exported function. If the end-user of my library is compiling in C++11 mode is it more likely that his use of regex will be std::regex or boost::regex ? IMO it is the former. Conversely if the end-user of my library is compiling in C++03 mode is it more likely that his use of regex will be std::regex or boost::regex ? That's a loaded question of course because std::regex won't be available to him if he compiles in C++03 mode. So my preferred usage of regex in my library, all else being equal, is to use boost::regex in C++03 mode and std::regex in C++11 mode. Even if Boost is a single distribution as it is now, so that boost::regex is always available for my Boost library I think it is advantageous to use the scheme just described.
The mechanism says that if std::regex exists, use it instead of boost::regex. If std::regex does not exist use boost::regex instead. If I don't have a dependency on boost::regex and std::regex supplies all my module's needs is it not better to use std::regex, so that in a future modular Boost distribution based system I will not have to distribute boost::regex with my library ?
So your anticipated future use case is that you want to create a distribution for your library that contains Boost.Config but does not contain Boost.Regex?
Yes, for C++11 mode.
There is some sort of disconnect here, because I can't make out what you are getting at.
You're putting the cart before the horse (Cartesius ante equum, as they say). The modular future hasn't arrived yet and we have no idea what it will be.
You are right. But I don't think it is unreasonable to consider that if it does arrive so that individual Boost libraries with their dependencies are distributed separately from the complete Boost tree as we do now, the elimination of dependencies for a particular distribution of a library is a good thing as long as it does not compromise the quality of the code.
Somebody, I forget who, wrote a Boost tool for extracting a library and its dependencies into a sort of mini-distribution.
John Maddock, the tool is called bcp.
I was kidding and referring to your bpm tool.
Edward Diener wrote:
I design a library which, let's say, takes a regex object as parameter to some exported function. If the end-user of my library is compiling in C++11 mode is it more likely that his use of regex will be std::regex or boost::regex ? IMO it is the former. Conversely if the end-user of my library is compiling in C++03 mode is it more likely that his use of regex will be std::regex or boost::regex ? That's a loaded question of course because std::regex won't be available to him if he compiles in C++03 mode. So my preferred usage of regex in my library, all else being equal, is to use boost::regex in C++03 mode and std::regex in C++11 mode.
This makes sense, and the question of dependencies and modular distributions is actually a side show. But you do realize that you'll be breaking your customer's C++03 (presumably tried and tested) code the moment he adds -std=c++11 in order to use a for(:) loop, right?
On 6/7/2015 6:41 AM, Peter Dimov wrote:
Edward Diener wrote:
I design a library which, let's say, takes a regex object as parameter to some exported function. If the end-user of my library is compiling in C++11 mode is it more likely that his use of regex will be std::regex or boost::regex ? IMO it is the former. Conversely if the end-user of my library is compiling in C++03 mode is it more likely that his use of regex will be std::regex or boost::regex ? That's a loaded question of course because std::regex won't be available to him if he compiles in C++03 mode. So my preferred usage of regex in my library, all else being equal, is to use boost::regex in C++03 mode and std::regex in C++11 mode.
This makes sense, and the question of dependencies and modular distributions is actually a side show.
But you do realize that you'll be breaking your customer's C++03 (presumably tried and tested) code the moment he adds -std=c++11 in order to use a for(:) loop, right?
Not if they use the macro system I propose in their own code to choose between Boost or C++ standard library equivalents. Or at least use the macro system I propose when interfacing with my library. Although for consistency's sake it would be easier to use the macro system in all places in their module, if they choose to not use it when not interfacing with my library that is their business. Breaking code when switching between C++03 mode and C++11 mode can occur outside the macro system I propose easily enough. Someone writes their code to use std::regex and compile in C++11 mode. They then switch to C++03 mode. Is std::regex still available in C++03 mode ? If it is not they have broken their code. It's not as if switching compile modes is as easy people suggest. A number of considerations have to be taken into account.
On 06/07/2015 05:17 AM, Edward Diener wrote:
I design a library which, let's say, takes a regex object as parameter to some exported function. If the end-user of my library is compiling in C++11 mode is it more likely that his use of regex will be std::regex or boost::regex ? IMO it is the former. Conversely if the end-user of my
What if your library uses extension in boost::regex that are not present in std::regex?
On 6/7/2015 7:05 AM, Bjorn Reese wrote:
On 06/07/2015 05:17 AM, Edward Diener wrote:
I design a library which, let's say, takes a regex object as parameter to some exported function. If the end-user of my library is compiling in C++11 mode is it more likely that his use of regex will be std::regex or boost::regex ? IMO it is the former. Conversely if the end-user of my
What if your library uses extension in boost::regex that are not present in std::regex?
In that case I don't use the macros for choosing between boost::regex and std::regex, but just decide to always use boost::regex in my interface. Using the macros are optional. Even bringing in the macros are optional, as including boost.config.hpp does not automatically include any of the macro header files.
On Sat, Jun 6, 2015 at 11:54 PM, Edward Diener
On 6/6/2015 8:26 AM, Andrey Semashev wrote:
On Friday 05 June 2015 21:07:20 Edward Diener wrote:
On 6/5/2015 6:35 PM, Andrey Semashev wrote:
In general, you won't get away with just macros, as autolinking is only present in MSVC & friends. This would also affect build system scripts.
Suppose I'm a (Boost) library writer; the library has a compiled part and I'm writing a Makefile/Jamfile. If I'm using these macros, I still have to know when to link and when not to link with Boost libs. This can be rather tricky as not only compiler versions should be checked but also their options; and it also needs to be in sync with Boost.Config. The same happens when I'm a user of a (Boost) library that uses these macros, only it becomes more difficult to be in sync with Boost.Config. My point is that since these macros don't actually abstract me away from the configuration, why would I use them?
They abstract you away from having to write complicated code which caters to whether or not a C++ standard library equivalent to a Boost library is available or not. They don't relieve the responsibility of a built library from naming itself in such a way that those linking with the library can do so successfully if auto-linking is not available.
I think you missed my point above. It's not about naming the library, its about the solution being incomplete to the point when you are not saved much by using these macros.
I do not understand what sort of completeness you desire.
I think I explained it multiple times now. The macros don't abstract away what implementation is being used - STL or Boost - because I have to deal with linking anyway. That's why the solution is incomplete.
My current view on this is if you're writing a C++11 library it's fairly logical for you to use STL11. No macros are needed for that. If you aim for C++03 compatibility, you should use STL03 and Boost where STL lacks something. Admittedly, this approach still has the library interoperability problem but at least your API and ABI are stable and do not depend on compiler options.
And suppose you want your library to work with either STL11 or STL03 ? Do you just decide that it is not possible so you have to choose one or the other ?
First, as I said, I don't see much point in this exercise. Second, if this affects API/ABI then this severely harms my library usability, so I definitely wouldn't do that. So yes, I decide which C++ level I will target and write the code accordingly.
That after all is what you are essentially saying a Boost library must do, is it not ?
I'm sorry, I didn't understand this question. I expressed my view on the matter, based on my experience. It's not an official Boost policy, if that's what you're asking.
I find that irritating, not because I think the Boost libraries are any worse than their C++ equivalents, but because I see no reason why I should either have dependencies on other Boost libraries when I don't need to or that I have to cut off all end-users of my library compiler implementations if I choose just C++11 mode and STL11.
I explained why. You are free to ignore my reasoning, of course, but I doubt your users will be happy in this case.
I understand your argument - after all C++ allows you to shoot yourself in the foot, so do your macros. But unlike C++ they don't make it really difficult. Maybe we just need a documented policy of use of these macros so that they don't get misused. Maybe we need testing, when the library and tests are compiled in different C++ modes. I don't know.
I have developed a series of proof of concept tests for each of the libraries the macro system supports in either C++03 or C++11 mode. I have not tried to add PRs for those tests for each Boost library yet because my macro system is not in Boost.config 'develop' yet, and I don't want failings test for no reason.
If I understood you correctly, that's not the kind of tests I was talking about.
Boost has implemented the notion that for libraries being built that the library name changes depending on whether or not the dynamic RTL or static RTL of the compiler implementation is being used. Also the library name changes depending on whether the library itself being built is a static or shared library. And there are a few more of these name manipulations which Boost enforces. I am simply arguing that we can come up with a means for doing the same on demand for C++ modes, not that we must do the same thing for C++ modes at all times.
Let me give a very simple practical use case and this will illustrate what I am trying to discuss.
I develop library EDS_LIB and it is a Boost library which must be built as a library and is not header-only, and my library uses regex in some interface it exports.
I have a decision to make: do I use Boost.regex and therefore work in any C++ mode or do I use std::regex and therefore works only in C++11 mode ( which I will assume supports the std::regex library ). Most people will say to use Boost.regex and be able to support any mode. Fair enough, but now EDS_LIB depends on Boost regex. If Boost ever goes to a more modular distribution all distribution of EDS_LIB must also include Boost regex.
Why? EDS_LIB would depend on Boost.Regex but not include it.
OTOH if I choose C++11 mode the dependency on Boost.regex goes away, but now you need to compile whatever uses EDS_LIB in C++11 mode else my library is useless to you.
Correct.
Now let's suppose, using my macro system, I can distribute my library as EDS_LIB in C++03 mode or EDS_LIB_C11 in C++11 mode. My exported interface using regex is:
#include
#include BOOST_CPP_REGEX_HDR void EdsFunction(BOOST_CPP_REGEX_NS::regex & rx); Now if you compile your library or application in C++03 mode you link with EDS_LIB and you get its dependency on Boost.regex. If you compile your library or application in C++11 mode you link with EDS_LIB_C11 and you no longer have its dependency on Boost.regex. In your application or library you use my macro system in order to pass the correct regex in either case without worrying about which it is:
#include
#include BOOST_CPP_REGEX_HDR BOOST_CPP_REGEX_NS::regex myregex("Some regular expression"); EdsFunction(myregex);
Where is the ABI problem in this case ? ( rhetorical question )
The ABI problem is right here. EDS_LIB, as it is distributed in a Linux distro, is built in C++03, and it is incompatible with user's code that is built in C++11. At least not in the way you describe. My suggested approach would be to avoid both Boost.Regex and std::regex in the binary interface - for example by passing strings in the ABI. You can still use whatever regex you like in the API, or even better - use concepts to accept any regex-like type, be that std::regex, boost::regex or boost::xpressive::regex - whatever the user happens to be using in his code.
Multiply the dependency beyond just regex to a few other Boost libraries which have C++11 standard library equivalents and you can see how the problem of choosing builds up. Either you are going to have a number of dependencies on other Boost libraries in C++03 mode or you are again going to be unusable in C++11 mode to other modules not using C++11.
I'm sorry, I don't see what the number of dependencies have to do with ABI stability.
You are saying: choose, either your library may have a number of dependencies when building it in C++03 mode, or your library will not have those dependencies but will be usable only in C++11 mode.
I am saying: having to choose is not acceptable in Boost as more compilers support C++11, but some either do not support C++11 or are not usable by end-users in C++11 mode.
It worked for me so far, I don't see the problem.
By the way, Boost is not the only project that attempts to maintain stable ABI regardless of the C++ mode. libstdc++ is also doing that, for example.
How many other library dependencies does libstdc++ have ? Then ask yourself how many other library dependencies does any given Boost library have ? Have I made my point ?
No, I don't think you did. How the number of dependencies have any relevance to API/ABI stability?
On 6/6/2015 7:23 PM, Andrey Semashev wrote:
On Sat, Jun 6, 2015 at 11:54 PM, Edward Diener
wrote: On 6/6/2015 8:26 AM, Andrey Semashev wrote:
On Friday 05 June 2015 21:07:20 Edward Diener wrote:
On 6/5/2015 6:35 PM, Andrey Semashev wrote:
In general, you won't get away with just macros, as autolinking is only present in MSVC & friends. This would also affect build system scripts.
Suppose I'm a (Boost) library writer; the library has a compiled part and I'm writing a Makefile/Jamfile. If I'm using these macros, I still have to know when to link and when not to link with Boost libs. This can be rather tricky as not only compiler versions should be checked but also their options; and it also needs to be in sync with Boost.Config. The same happens when I'm a user of a (Boost) library that uses these macros, only it becomes more difficult to be in sync with Boost.Config. My point is that since these macros don't actually abstract me away from the configuration, why would I use them?
They abstract you away from having to write complicated code which caters to whether or not a C++ standard library equivalent to a Boost library is available or not. They don't relieve the responsibility of a built library from naming itself in such a way that those linking with the library can do so successfully if auto-linking is not available.
I think you missed my point above. It's not about naming the library, its about the solution being incomplete to the point when you are not saved much by using these macros.
I do not understand what sort of completeness you desire.
I think I explained it multiple times now. The macros don't abstract away what implementation is being used - STL or Boost - because I have to deal with linking anyway. That's why the solution is incomplete.
I have repeated again and again that for built libraries, as opposed to header-only libraries, a system of distinct names for the same library depending on whether the library is compiled in C++03 mode or C++11 mode can solve this problem. I know that you think that solving this problem is the responsibility of my macro solution, and therefore the macros are not worthwhile using unless I solve it in my implementation. That's your right and I am not going to bother to argue with it. I think we are just at a point of basic disagreement on this issue.
My current view on this is if you're writing a C++11 library it's fairly logical for you to use STL11. No macros are needed for that. If you aim for C++03 compatibility, you should use STL03 and Boost where STL lacks something. Admittedly, this approach still has the library interoperability problem but at least your API and ABI are stable and do not depend on compiler options.
And suppose you want your library to work with either STL11 or STL03 ? Do you just decide that it is not possible so you have to choose one or the other ?
First, as I said, I don't see much point in this exercise. Second, if this affects API/ABI then this severely harms my library usability, so I definitely wouldn't do that. So yes, I decide which C++ level I will target and write the code accordingly.
That after all is what you are essentially saying a Boost library must do, is it not ?
I'm sorry, I didn't understand this question. I expressed my view on the matter, based on my experience. It's not an official Boost policy, if that's what you're asking.
I find that irritating, not because I think the Boost libraries are any worse than their C++ equivalents, but because I see no reason why I should either have dependencies on other Boost libraries when I don't need to or that I have to cut off all end-users of my library compiler implementations if I choose just C++11 mode and STL11.
I explained why. You are free to ignore my reasoning, of course, but I doubt your users will be happy in this case.
I understand your argument - after all C++ allows you to shoot yourself in the foot, so do your macros. But unlike C++ they don't make it really difficult. Maybe we just need a documented policy of use of these macros so that they don't get misused. Maybe we need testing, when the library and tests are compiled in different C++ modes. I don't know.
I have developed a series of proof of concept tests for each of the libraries the macro system supports in either C++03 or C++11 mode. I have not tried to add PRs for those tests for each Boost library yet because my macro system is not in Boost.config 'develop' yet, and I don't want failings test for no reason.
If I understood you correctly, that's not the kind of tests I was talking about.
Boost has implemented the notion that for libraries being built that the library name changes depending on whether or not the dynamic RTL or static RTL of the compiler implementation is being used. Also the library name changes depending on whether the library itself being built is a static or shared library. And there are a few more of these name manipulations which Boost enforces. I am simply arguing that we can come up with a means for doing the same on demand for C++ modes, not that we must do the same thing for C++ modes at all times.
Let me give a very simple practical use case and this will illustrate what I am trying to discuss.
I develop library EDS_LIB and it is a Boost library which must be built as a library and is not header-only, and my library uses regex in some interface it exports.
I have a decision to make: do I use Boost.regex and therefore work in any C++ mode or do I use std::regex and therefore works only in C++11 mode ( which I will assume supports the std::regex library ). Most people will say to use Boost.regex and be able to support any mode. Fair enough, but now EDS_LIB depends on Boost regex. If Boost ever goes to a more modular distribution all distribution of EDS_LIB must also include Boost regex.
Why? EDS_LIB would depend on Boost.Regex but not include it.
How in the world would EDS_LIB depend on Boost.Regex but not have it part of the distribution of EDS_LIB if we go with a modular Boost distribution where EDS_LIB could be distributed by itself with its dependencies ?
OTOH if I choose C++11 mode the dependency on Boost.regex goes away, but now you need to compile whatever uses EDS_LIB in C++11 mode else my library is useless to you.
Correct.
Now let's suppose, using my macro system, I can distribute my library as EDS_LIB in C++03 mode or EDS_LIB_C11 in C++11 mode. My exported interface using regex is:
#include
#include BOOST_CPP_REGEX_HDR void EdsFunction(BOOST_CPP_REGEX_NS::regex & rx); Now if you compile your library or application in C++03 mode you link with EDS_LIB and you get its dependency on Boost.regex. If you compile your library or application in C++11 mode you link with EDS_LIB_C11 and you no longer have its dependency on Boost.regex. In your application or library you use my macro system in order to pass the correct regex in either case without worrying about which it is:
#include
#include BOOST_CPP_REGEX_HDR BOOST_CPP_REGEX_NS::regex myregex("Some regular expression"); EdsFunction(myregex);
Where is the ABI problem in this case ? ( rhetorical question )
The ABI problem is right here. EDS_LIB, as it is distributed in a Linux distro, is built in C++03, and it is incompatible with user's code that is built in C++11. At least not in the way you describe.
EDS_LIB distribution is not distributed for C++11 use. For that my previously mentioned EDS_LIB_C11 is distributed with its dependencies for C++11 use.
My suggested approach would be to avoid both Boost.Regex and std::regex in the binary interface - for example by passing strings in the ABI. You can still use whatever regex you like in the API, or even better - use concepts to accept any regex-like type, be that std::regex, boost::regex or boost::xpressive::regex - whatever the user happens to be using in his code.
I know you are not kidding but I consider your solution "not optimal". Your solution is that two perfectly usable versions of regex exist but I need to manufacture another. Needless to say that is not my idea of programming in this situation.
Multiply the dependency beyond just regex to a few other Boost libraries which have C++11 standard library equivalents and you can see how the problem of choosing builds up. Either you are going to have a number of dependencies on other Boost libraries in C++03 mode or you are again going to be unusable in C++11 mode to other modules not using C++11.
I'm sorry, I don't see what the number of dependencies have to do with ABI stability.
You are saying: choose, either your library may have a number of dependencies when building it in C++03 mode, or your library will not have those dependencies but will be usable only in C++11 mode.
I am saying: having to choose is not acceptable in Boost as more compilers support C++11, but some either do not support C++11 or are not usable by end-users in C++11 mode.
It worked for me so far, I don't see the problem.
By the way, Boost is not the only project that attempts to maintain stable ABI regardless of the C++ mode. libstdc++ is also doing that, for example.
How many other library dependencies does libstdc++ have ? Then ask yourself how many other library dependencies does any given Boost library have ? Have I made my point ?
No, I don't think you did. How the number of dependencies have any relevance to API/ABI stability?
What does API/ABI stability mean in this context to you ? We are probably discussing this at cross-purposes because my interpretation of what it means is not what you mean.
On 07.06.2015 06:39, Edward Diener wrote:
On 6/6/2015 7:23 PM, Andrey Semashev wrote:
The macros don't abstract away what implementation is being used - STL or Boost - because I have to deal with linking anyway. That's why the solution is incomplete.
I have repeated again and again that for built libraries, as opposed to header-only libraries, a system of distinct names for the same library depending on whether the library is compiled in C++03 mode or C++11 mode can solve this problem.
I don't see how.
I have a decision to make: do I use Boost.regex and therefore work in any C++ mode or do I use std::regex and therefore works only in C++11 mode ( which I will assume supports the std::regex library ). Most people will say to use Boost.regex and be able to support any mode. Fair enough, but now EDS_LIB depends on Boost regex. If Boost ever goes to a more modular distribution all distribution of EDS_LIB must also include Boost regex.
Why? EDS_LIB would depend on Boost.Regex but not include it.
How in the world would EDS_LIB depend on Boost.Regex but not have it part of the distribution of EDS_LIB if we go with a modular Boost distribution where EDS_LIB could be distributed by itself with its dependencies ?
Huh? I didn't know we were going for that kind of modularity. My understanding was that modular Boost would consist of multiple independent libraries (which distribute only their own code) and a tool that is able to download a library and its dependencies. If we're going to bundle a library and all its dependencies together then that's not the modular Boost I want to use or develop.
Now let's suppose, using my macro system, I can distribute my library as EDS_LIB in C++03 mode or EDS_LIB_C11 in C++11 mode. My exported interface using regex is:
#include
#include BOOST_CPP_REGEX_HDR void EdsFunction(BOOST_CPP_REGEX_NS::regex & rx); Now if you compile your library or application in C++03 mode you link with EDS_LIB and you get its dependency on Boost.regex. If you compile your library or application in C++11 mode you link with EDS_LIB_C11 and you no longer have its dependency on Boost.regex. In your application or library you use my macro system in order to pass the correct regex in either case without worrying about which it is:
#include
#include BOOST_CPP_REGEX_HDR BOOST_CPP_REGEX_NS::regex myregex("Some regular expression"); EdsFunction(myregex);
Where is the ABI problem in this case ? ( rhetorical question )
The ABI problem is right here. EDS_LIB, as it is distributed in a Linux distro, is built in C++03, and it is incompatible with user's code that is built in C++11. At least not in the way you describe.
EDS_LIB distribution is not distributed for C++11 use. For that my previously mentioned EDS_LIB_C11 is distributed with its dependencies for C++11 use.
What exactly do you mean by "distribution"? Does it include library headers? Are these headers different in EDS_LIB and EDS_LIB_C11? If both are yes, do they not conflict?
My suggested approach would be to avoid both Boost.Regex and std::regex in the binary interface - for example by passing strings in the ABI. You can still use whatever regex you like in the API, or even better - use concepts to accept any regex-like type, be that std::regex, boost::regex or boost::xpressive::regex - whatever the user happens to be using in his code.
I know you are not kidding but I consider your solution "not optimal". Your solution is that two perfectly usable versions of regex exist but I need to manufacture another. Needless to say that is not my idea of programming in this situation.
Why would you have to manufacture one?
How many other library dependencies does libstdc++ have ? Then ask yourself how many other library dependencies does any given Boost library have ? Have I made my point ?
No, I don't think you did. How the number of dependencies have any relevance to API/ABI stability?
What does API/ABI stability mean in this context to you ?
For the course of this discussion it means that API/ABI do not depend on compiler options, including C++ mode.
On 5 Jun 2015 at 5:30, Edward Diener wrote:
I don't know what "the right approach" would be but this is one approach that does work easily, following the documentation I have written about it and added to the Boost.config documentation.
Firstly, this is a long overdue patch and I find it a hugely welcome development. Thank you Edward for taking the time to implement it.
If I have missed any Boost libraries which have a close C++ standard equivalent just tell me and I will add it with some added tests for that particular library.
I didn't see system_error?
5) I wanted to push it to 'develop' and let others use it and add the per library PR's to test it. If it was found to be flawed or could be better in any way I could then change it on 'develop', and if people were satisfied with it as a workable solution it could eventually be merged to 'master'. If not it could be easily removed if necessary since it exists in its own header files apart from the rest of Boost.config. Even its documentation is a separate Boost.config .qbk file.
Here's a crazy idea: If Boost.Build is in >= C++ 11 build mode, turn all these macros on by default. That should ease testing enormously. Build needs to gain an official C++ 11 build mode first though. Something where libraries in their Jamfile can say "I can only compile with C++11 or better, so if not >= C++ 11 then ignore this library during build".
If there are better interoperable systems I would love to hear about them. But for me personally any system where I have to jump through hoops simply to be able to write code which works whether I am using a Boost library or its C++ standard library equivalent, will not be worth it.
I think this support is a great first step to making Boost less obsolete in a C++ 11 world. It doesn't solve all the other problems Boost has, but it's still a huge improvement.
Questions, concerns etc are welcome.
My only real worry is the ABI problems. You need to permute the symbols being linked to avoid config mismatches colliding in an unhelpful way. Perhaps for each config macro have during build the library output an extern dll visible empty function with a mangled name representing the config. On use, import and use that function. This should generate link errors if one is trying to use a config against a binary not built the same way. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/
On 6/6/2015 12:14 PM, Niall Douglas wrote:
On 5 Jun 2015 at 5:30, Edward Diener wrote:
I don't know what "the right approach" would be but this is one approach that does work easily, following the documentation I have written about it and added to the Boost.config documentation.
Firstly, this is a long overdue patch and I find it a hugely welcome development. Thank you Edward for taking the time to implement it.
If I have missed any Boost libraries which have a close C++ standard equivalent just tell me and I will add it with some added tests for that particular library.
I didn't see system_error?+
I will look into it. Thanks !
5) I wanted to push it to 'develop' and let others use it and add the per library PR's to test it. If it was found to be flawed or could be better in any way I could then change it on 'develop', and if people were satisfied with it as a workable solution it could eventually be merged to 'master'. If not it could be easily removed if necessary since it exists in its own header files apart from the rest of Boost.config. Even its documentation is a separate Boost.config .qbk file.
Here's a crazy idea: If Boost.Build is in >= C++ 11 build mode, turn all these macros on by default. That should ease testing enormously.
I am not sure what you mean by "turn all these macros on by default." If Boost Build is in C++11 mode then the underlying Boost.config macros, upon which each XXX library macro is based, will no doubt show that the C++11 library is available for use. This in turn means that if a particular boost/config/cpp/XXX.hpp header is included by the end-user the corresponding BOOST_CPP_HAS_XXX macro will be 1 and not 0. Of course it is barely possible that c++11 mode for a particular compiler/version implementation does not support a mandated C++11 library, but that is not anything Boost or my XXX library macro can do anything about. But at least that fact will be totally consistent for all modules built with that particcular compiler/version implementation. So in effect in C++11 mode for a compiler/version implementation all of the corresponding BOOST_CPP_HAS_XXX macros for each XXX library should automatically be 1.
Build needs to gain an official C++ 11 build mode first though. Something where libraries in their Jamfile can say "I can only compile with C++11 or better, so if not >= C++ 11 then ignore this library during build".
You can do that with my macros, for any one of the libraries supported,
by simply issuing a preprocessor #error. I show this in the
documentation. Essentially if a library needs C++11 mode to be built
because it requires a particular C++11 library equivalent to be used
instead of the Boost library it can create code for the equivalent
library XXX of:
#include
If there are better interoperable systems I would love to hear about them. But for me personally any system where I have to jump through hoops simply to be able to write code which works whether I am using a Boost library or its C++ standard library equivalent, will not be worth it.
I think this support is a great first step to making Boost less obsolete in a C++ 11 world. It doesn't solve all the other problems Boost has, but it's still a huge improvement.
Thanks ! It has very practical use for me in a library on which I am working, which will be a header-only template library.
Questions, concerns etc are welcome.
My only real worry is the ABI problems. You need to permute the symbols being linked to avoid config mismatches colliding in an unhelpful way.
The issue as far as ABI comes down to the ability of using such a dual-mode library that is a built library and is not a header only library. My point of view is that Boost needs to establish a way so that a library built in C++03 mode could be named slightly differently from the same library built in C++11 mode. We already have a system in place which can name a library differently depending on whether it uses the dynamic or static RTL of its implementation, or whether the library itself is a static lib or a shared lib, among other naming conventions. What I am positing for a built library is that the developer of that library should have the ability to specify that his library have a different name depending on whether it is C++03 or C++11 mode, and that this choice should work so that the correct name is used during both a link of the library and when that library is being used by another library. Boost.config already has a system of auto-linking which must be coordinated with Boost Build to use the correct library name, so adding the compile-time ability to change the name slightly between a C++03 mode build and a C++11 mode build must also I believe be co-ordinated with Boost Build.
Perhaps for each config macro have during build the library output an extern dll visible empty function with a mangled name representing the config. On use, import and use that function. This should generate link errors if one is trying to use a config against a binary not built the same way.
This elaboration does not seem necessary to me, but I don't really understand its reason. I believe the problem can be solved by a library naming convention that can give a C++03 library a slightly different name than a C++11 library, but only if the library developer needs to do this. The use case I see for this need can be illustrated in this way. One creates a built dual-mode library using my macros, and the interface to my library specifies that, let's say, in C++03 mode you pass a boost::ratio object to some exported function while in C++11 mode you pass its C++ standard equivalent std::ratio object to some function. A user of my library compiling in C++03 mode will link to the version name of my library built in C++03 mode, and using my macros will automatically be passing the correct ratio object to my library's functionality. Likewise a user of my library compiling in C++11 mode will link to my library built in C++11 mode, and once again using my macros will automatically be passing the correct ratio object to my library's functionality. As long as the correct name of my library is being linked the ABI problem of using the correct library is solved. So the only ABI problem I see here is establishing a convention and a system in Boost by which a dual-mode library using one or more of my set of XXX macros might want to be built using slightly different names for C++03 and C++11 mode. You may know of ABI problems between a library built for C++03 or C++11 which are outside the problem I have tried to solve with my macro system. But my macros themselves are only meant to solve a particular problem and not the perhaps larger one of ABI compatibility between a library built in one C++ mode or another or possibly both. It is important that Boost not consign its libraries to support only one particular subset of Boost libraries and/or C++11 equivalent libraries. This will prevent Boost library development from moving into the C+11 world of programming when the idioms and libraries of C++11 prove highly useful to C++ library design and development. My macro system is an effort to support both C++ modes with the least amount of syntactical problems. I have no doubt as more and more compilers support C++11 more thoroughly that new Boost libraries will use C++11 features to enhance their ability. But the reality is currently such that until a full transition is made by all major compilers to support C++11, C++14, and beyond ( C++17 ? ) library developers may still target new libraries to accomodate the C++03 standard as the lowest common denominator, so to speak, of C++ compatibility.
On 6 Jun 2015 at 15:30, Edward Diener wrote:
Here's a crazy idea: If Boost.Build is in >= C++ 11 build mode, turn all these macros on by default. That should ease testing enormously.
I am not sure what you mean by "turn all these macros on by default."
If Boost Build is in C++11 mode then the underlying Boost.config macros, upon which each XXX library macro is based, will no doubt show that the C++11 library is available for use. This in turn means that if a particular boost/config/cpp/XXX.hpp header is included by the end-user the corresponding BOOST_CPP_HAS_XXX macro will be 1 and not 0. Of course it is barely possible that c++11 mode for a particular compiler/version implementation does not support a mandated C++11 library, but that is not anything Boost or my XXX library macro can do anything about. But at least that fact will be totally consistent for all modules built with that particcular compiler/version implementation.
So in effect in C++11 mode for a compiler/version implementation all of the corresponding BOOST_CPP_HAS_XXX macros for each XXX library should automatically be 1.
Sorry. I missed that you need to explicitly opt into the switching functionality by using a macro which expands into the true underlying implementation. I thought you wouldn't need to prefix every single use with a macro. APIBind does the same thing as you've done using aliasing and is therefore macro-free. Sadly aliasing is C++ 11 only. One could emulate it using shims, but they participate in overload resolution :( If a library has its own namespace though (most of the newer ones do), a simple namespace alias can save a lot of ugly macros. You might add that to your docs.
But my macros do not have, nor are they intended to have, the general ability to just say that if C++11 mode is not being used it should be an error.
It's more the case that right now each C++ 11 mandatory library
simply forces on -std=c++11 in their Jamfile. That seems silly to me,
and guaranteed to cause problems once the first C++ 11 mandatory
library enters Boost.
What we need is something like <requirements>
I think this support is a great first step to making Boost less obsolete in a C++ 11 world. It doesn't solve all the other problems Boost has, but it's still a huge improvement.
Thanks ! It has very practical use for me in a library on which I am working, which will be a header-only template library.
Did I see that you've patched all the other Boost libraries such that any Boost library which uses regex can be switched into std::regex? If so, cool. But ABI worrying. If not, then it might explain me getting confused below (if so disregard what I say below).
Questions, concerns etc are welcome.
My only real worry is the ABI problems. You need to permute the symbols being linked to avoid config mismatches colliding in an unhelpful way.
The issue as far as ABI comes down to the ability of using such a dual-mode library that is a built library and is not a header only library.
Not entirely. What if I build my DLL A which configures Boost header only libraries with std and someone else builds DLL B which configures Boost header only libraries with boost and then a third party tries loading both DLLs into the same process? On Windows it would probably somewhat work, but god help you if you try passing object instances from one DLL to the other.
My point of view is that Boost needs to establish a way so that a library built in C++03 mode could be named slightly differently from the same library built in C++11 mode. We already have a system in place which can name a library differently depending on whether it uses the dynamic or static RTL of its implementation, or whether the library itself is a static lib or a shared lib, among other naming conventions. What I am positing for a built library is that the developer of that library should have the ability to specify that his library have a different name depending on whether it is C++03 or C++11 mode, and that this choice should work so that the correct name is used during both a link of the library and when that library is being used by another library.
Similar to APIBind's use of an ABI mangled inline namespace.
Boost.config already has a system of auto-linking which must be coordinated with Boost Build to use the correct library name, so adding the compile-time ability to change the name slightly between a C++03 mode build and a C++11 mode build must also I believe be co-ordinated with Boost Build.
Apart from GCC not supporting auto-linking, great. I really wish GCC did support auto-linking. It's a trivial feature add, the only hard part is getting it past the gatekeepers for the GCC tooling.
It is important that Boost not consign its libraries to support only one particular subset of Boost libraries and/or C++11 equivalent libraries. This will prevent Boost library development from moving into the C+11 world of programming when the idioms and libraries of C++11 prove highly useful to C++ library design and development. My macro system is an effort to support both C++ modes with the least amount of syntactical problems. I have no doubt as more and more compilers support C++11 more thoroughly that new Boost libraries will use C++11 features to enhance their ability. But the reality is currently such that until a full transition is made by all major compilers to support C++11, C++14, and beyond ( C++17 ? ) library developers may still target new libraries to accomodate the C++03 standard as the lowest common denominator, so to speak, of C++ compatibility.
As everyone knows, my personal position on that is that we are long overdue a C++ 11 only separate Boost distro. Additional distros consisting of just the well maintained libraries would be even better. That would reduce Boost to eighty or ninety libraries, and help users not constantly waste time using Boost libraries riddled with bugs that will never be fixed. It is deeply unfair that we do that to users. Undermaintained libraries should, as a minimum, have a big flashing warning next to their name with a suggestion that if you would like to take over maintaining that library we can do you a deal (as per the new policy agreed at C++ Now). Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/
On 6/7/2015 5:39 AM, Niall Douglas wrote:
On 6 Jun 2015 at 15:30, Edward Diener wrote:
Here's a crazy idea: If Boost.Build is in >= C++ 11 build mode, turn all these macros on by default. That should ease testing enormously.
I am not sure what you mean by "turn all these macros on by default."
If Boost Build is in C++11 mode then the underlying Boost.config macros, upon which each XXX library macro is based, will no doubt show that the C++11 library is available for use. This in turn means that if a particular boost/config/cpp/XXX.hpp header is included by the end-user the corresponding BOOST_CPP_HAS_XXX macro will be 1 and not 0. Of course it is barely possible that c++11 mode for a particular compiler/version implementation does not support a mandated C++11 library, but that is not anything Boost or my XXX library macro can do anything about. But at least that fact will be totally consistent for all modules built with that particcular compiler/version implementation.
So in effect in C++11 mode for a compiler/version implementation all of the corresponding BOOST_CPP_HAS_XXX macros for each XXX library should automatically be 1.
Sorry. I missed that you need to explicitly opt into the switching functionality by using a macro which expands into the true underlying implementation. I thought you wouldn't need to prefix every single use with a macro.
APIBind does the same thing as you've done using aliasing and is therefore macro-free. Sadly aliasing is C++ 11 only. One could emulate it using shims, but they participate in overload resolution :(
If a library has its own namespace though (most of the newer ones do), a simple namespace alias can save a lot of ugly macros. You might add that to your docs.
Good idea !
You could also use a using directive, with its usual pitfalls, easily
enough:
#include
But my macros do not have, nor are they intended to have, the general ability to just say that if C++11 mode is not being used it should be an error.
It's more the case that right now each C++ 11 mandatory library simply forces on -std=c++11 in their Jamfile. That seems silly to me, and guaranteed to cause problems once the first C++ 11 mandatory library enters Boost.
What we need is something like <requirements>
2014. Or similar. I agree this is a totally separate issue to your patch.
I think this support is a great first step to making Boost less obsolete in a C++ 11 world. It doesn't solve all the other problems Boost has, but it's still a huge improvement.
Thanks ! It has very practical use for me in a library on which I am working, which will be a header-only template library.
Did I see that you've patched all the other Boost libraries such that any Boost library which uses regex can be switched into std::regex?
No, I did not do that. What I have done locally, but not yet created forks and PRs, is to add simple tests to each Boost library that show that the technique of using my macros will work whether one compiles in C++11 mode or not.
If so, cool. But ABI worrying. If not, then it might explain me getting confused below (if so disregard what I say below).
Questions, concerns etc are welcome.
My only real worry is the ABI problems. You need to permute the symbols being linked to avoid config mismatches colliding in an unhelpful way.
The issue as far as ABI comes down to the ability of using such a dual-mode library that is a built library and is not a header only library.
Not entirely. What if I build my DLL A which configures Boost header only libraries with std and someone else builds DLL B which configures Boost header only libraries with boost and then a third party tries loading both DLLs into the same process?
On Windows it would probably somewhat work, but god help you if you try passing object instances from one DLL to the other.
This is no different from anyone doing this manually without the use of my macros. Any DLL can pick which libraries it wants to use, whether a Boost library or a C++ standard library equivalent. If I create DLL A which uses Boost regex in its interface and DLL B which uses the C++11 std::regex in its interface, naturally I can't mix them in the sense of trying to pass a Boost regex object to a library that expects a std::regex object or vice versa. As far as actually loading both libraries that in itself should cause no problems AFAICS.
My point of view is that Boost needs to establish a way so that a library built in C++03 mode could be named slightly differently from the same library built in C++11 mode. We already have a system in place which can name a library differently depending on whether it uses the dynamic or static RTL of its implementation, or whether the library itself is a static lib or a shared lib, among other naming conventions. What I am positing for a built library is that the developer of that library should have the ability to specify that his library have a different name depending on whether it is C++03 or C++11 mode, and that this choice should work so that the correct name is used during both a link of the library and when that library is being used by another library.
Similar to APIBind's use of an ABI mangled inline namespace.
Boost.config already has a system of auto-linking which must be coordinated with Boost Build to use the correct library name, so adding the compile-time ability to change the name slightly between a C++03 mode build and a C++11 mode build must also I believe be co-ordinated with Boost Build.
Apart from GCC not supporting auto-linking, great.
I really wish GCC did support auto-linking. It's a trivial feature add, the only hard part is getting it past the gatekeepers for the GCC tooling.
I agree that GCC providing auto-linking would be good. But even without auto-linking I think that Boost Build already might have some way to "name" a library based on its compile time parameters.
It is important that Boost not consign its libraries to support only one particular subset of Boost libraries and/or C++11 equivalent libraries. This will prevent Boost library development from moving into the C+11 world of programming when the idioms and libraries of C++11 prove highly useful to C++ library design and development. My macro system is an effort to support both C++ modes with the least amount of syntactical problems. I have no doubt as more and more compilers support C++11 more thoroughly that new Boost libraries will use C++11 features to enhance their ability. But the reality is currently such that until a full transition is made by all major compilers to support C++11, C++14, and beyond ( C++17 ? ) library developers may still target new libraries to accomodate the C++03 standard as the lowest common denominator, so to speak, of C++ compatibility.
As everyone knows, my personal position on that is that we are long overdue a C++ 11 only separate Boost distro.
Additional distros consisting of just the well maintained libraries would be even better. That would reduce Boost to eighty or ninety libraries, and help users not constantly waste time using Boost libraries riddled with bugs that will never be fixed. It is deeply unfair that we do that to users. Undermaintained libraries should, as a minimum, have a big flashing warning next to their name with a suggestion that if you would like to take over maintaining that library we can do you a deal (as per the new policy agreed at C++ Now).
I know your opinion about a separate Boost for C++11 libraries. My solution is different. I think libraries for C++11 can coexist in Boost with libraries supporting C++03. I see nothing wrong with the ability of header-only libraries being used in dual mode with my macros. As far as built libraries if Boost could come up with a naming solution so that the C++11 version of a library has a slightly different name than its C++03 counterpart I think that will work fine. Most of the talk about the problems of my macro system presupposes that programmers using Boost will mistakenly try to use a C++11 version of a library during a C++03 mode build and vice versa, and therefore the system must be flawed. Naturally I don't agree but I do understand the reticence of others to accept a dual mode system such as I am proposing.
Edward Diener wrote:
Most of the talk about the problems of my macro system presupposes that programmers using Boost will mistakenly try to use a C++11 version of a library during a C++03 mode build and vice versa, and therefore the system must be flawed.
This was some of the talk but I'm not sure about "most". A substantial part of the talk was about programmers wanting to use boost::regex even when the compiler happens to be in C++11 mode. In other words, talk that challenges your assumption that
If the end-user of my library is compiling in C++11 mode is it more likely that his use of regex will be std::regex or boost::regex ? IMO it is the former.
There are several good reasons to prefer boost::regex. First, the one I pointed out, you want to maintain a single code base that compiles under C++03 and C++11. Second, you want to use boost::regex's extensions that std::regex doesn't have. Third, you want predictable performance that is independent of the standard library in use. On the other side of the coin, we have the desire to avoid use of Boost when use of standard facilities would suffice, which is real and legitimate. However, in my experience at least, this desire is only strong when you can avoid use of Boost _altogether_, which is not the case under discussion.
On 6/7/2015 10:36 AM, Peter Dimov wrote:
Edward Diener wrote:
Most of the talk about the problems of my macro system presupposes that programmers using Boost will mistakenly try to use a C++11 version of a library during a C++03 mode build and vice versa, and therefore the system must be flawed.
This was some of the talk but I'm not sure about "most". A substantial part of the talk was about programmers wanting to use boost::regex even when the compiler happens to be in C++11 mode. In other words, talk that challenges your assumption that
If the end-user of my library is compiling in C++11 mode is it more likely that his use of regex will be std::regex or boost::regex ? IMO it is the former.
There are several good reasons to prefer boost::regex. First, the one I pointed out, you want to maintain a single code base that compiles under C++03 and C++11. Second, you want to use boost::regex's extensions that std::regex doesn't have. Third, you want predictable performance that is independent of the standard library in use.
If you use my macro system you can continue to maintain a single code base under C++03 and C++11. Sometimes it is the other way around and a C++ standard library equivalent has functionality which its corresponding Boost library does not have.
On the other side of the coin, we have the desire to avoid use of Boost when use of standard facilities would suffice, which is real and legitimate. However, in my experience at least, this desire is only strong when you can avoid use of Boost _altogether_, which is not the case under discussion.
It is the case under discussion if there is no other use of Boost libraries outside of the ones which have their equivalent in the C++ standard library for a given module. If the above is not the case I don't think that the desire to avoid using Boost altogether is realistic either. Boost has approximately 100 or so libraries which are not "duplicated" by C++ standard library equivalents. Why would anyone refuse to use any of those 100 or so libraries on principle if the use of a Boost library made their programming easier ? I understand that in the present incarnation of Boost as a single distribution that the attempt to use C++ standard library equivalents to Boost libraries when compiling in C++11 mode does not offer much of an advantage. But if and when in a future incarnation of Boost an individual Boost library, whether header-only or not, along with its dependencies can be distributed and used outside the currently monolithic Boost distribution it will be an advantage to be able to use C++ standard library equivalents to Boost libraries.
On 07/06/2015 15:36, Peter Dimov wrote:
Edward Diener wrote:
Most of the talk about the problems of my macro system presupposes that programmers using Boost will mistakenly try to use a C++11 version of a library during a C++03 mode build and vice versa, and therefore the system must be flawed.
This was some of the talk but I'm not sure about "most". A substantial part of the talk was about programmers wanting to use boost::regex even when the compiler happens to be in C++11 mode. In other words, talk that challenges your assumption that
If the end-user of my library is compiling in C++11 mode is it more likely that his use of regex will be std::regex or boost::regex ? IMO it is the former.
There are several good reasons to prefer boost::regex. First, the one I pointed out, you want to maintain a single code base that compiles under C++03 and C++11. Second, you want to use boost::regex's extensions that std::regex doesn't have. Third, you want predictable performance that is independent of the standard library in use.
Right. But if lib X prefers/needs to use the Boost version always, they don't have to use this mechanism.
On the other side of the coin, we have the desire to avoid use of Boost when use of standard facilities would suffice, which is real and legitimate. However, in my experience at least, this desire is only strong when you can avoid use of Boost _altogether_, which is not the case under discussion. Right, we're nowhere near having a package manager that's smart enough to avoid dependence on boost::whatever if the user tells it they have a C++11 compiler.
I guess my concerns are somewhat different from those already expressed: * I'm not sure that this adds much over the existing macros BOOST_NO_CXX11_HDR_REGEX etc. * If this evolved into a more "complete" solution, then (a) It doesn't belong in Config (too many dependencies), and (b) I would worry that we repeat the mistake of Boost.TR1 - which is to say creating that particular unmaintainable monster it in the first place -just ask the author ;) * Folks are correct to be concerned about ABI issues: we not that long ago changed 'nix installs to install "one true binary" for each library as there was *very* strong user preference for that. Splitting into '03 and '11 binaries is IMO a significant retrograde step. If you do that expect endless newbie support requests wondering why things don't work. On the other hand: * I can see a legitimate use for this as a library internal (rather like what Math does with std::tuple and boost::tuple). * The need to have different linking requirements in Boost.Build is a solved issue - just use check_target_builds to set the dependency. So... I guess what I would like to see expressed, is what are the concrete use cases for this? What do *you* want to use it for? And finally, you are aware that there are 3 tuples available? boost::, fusion:: and std::, and they they all are slightly different? Oh and std::tr1::tuple too ;) What I suspect we will see more of, is libraries becoming implementation agnostic - "give me something that looks like a tuple/thread/future/function and I'll go off and do the right thing". The latest Math code does that with tuple types, and it was a pain in the neck to get working (or possibly I was just being dense at the time), certainly the hoops you have to jump through to support that go way beyond the scope of this addition. Regards, John.
John Maddock wrote:
Right. But if lib X prefers/needs to use the Boost version always, they don't have to use this mechanism.
What I'm saying is more like lib X has a dual interface, but _the user_ of lib X wants to use the boost:: version, whereas lib X detects C++11 and provides the std:: version. Lib X is #if CXX11 void libx_f( std::regex const & rx ); #else void libx_f( boost::regex const & rx ); #endif but the user wants to continue using boost::regex under C++11. This could in principle be addressed in some way by giving the user the option to override libX's decision to go with std::regex.
Right. But if lib X prefers/needs to use the Boost version always, they don't have to use this mechanism.
What I'm saying is more like lib X has a dual interface, but _the user_ of lib X wants to use the boost:: version, whereas lib X detects C++11 and provides the std:: version.
Got you. Yes that's an issue, and probably the only solution is for each library to have a macro that signals which to use :( John.
On 6/7/2015 1:29 PM, Peter Dimov wrote:
John Maddock wrote:
Right. But if lib X prefers/needs to use the Boost version always, they don't have to use this mechanism.
What I'm saying is more like lib X has a dual interface, but _the user_ of lib X wants to use the boost:: version, whereas lib X detects C++11 and provides the std:: version.
Lib X is
#if CXX11
void libx_f( std::regex const & rx );
#else
void libx_f( boost::regex const & rx );
#endif
but the user wants to continue using boost::regex under C++11.
This could in principle be addressed in some way by giving the user the option to override libX's decision to go with std::regex.
I have thought of letting the end-user override libX's decision. For a currently supported XXX library in my macro system I could allow a BOOST_CPP_XXX_USE_BOOST be defined by the user which would force the use of the Boost library even in C++11 mode. I have also contemplated a convenient BOOST_CPP_USE_BOOST macro being defined by the end-user which would force the use of a Boost library for any XXX library in C++11 mode. Programming this idea into my macro system is trivial. But suppose compiling in C++11 mode one TU has BOOST_CPP_XXX_USE_BOOST defined and another TU does not and both include some interface affected by this decision. I think in this case KISS is better than the kiss of death <g>.
On 6/7/2015 1:04 PM, John Maddock wrote:
On 07/06/2015 15:36, Peter Dimov wrote:
Edward Diener wrote:
Most of the talk about the problems of my macro system presupposes that programmers using Boost will mistakenly try to use a C++11 version of a library during a C++03 mode build and vice versa, and therefore the system must be flawed.
This was some of the talk but I'm not sure about "most". A substantial part of the talk was about programmers wanting to use boost::regex even when the compiler happens to be in C++11 mode. In other words, talk that challenges your assumption that
If the end-user of my library is compiling in C++11 mode is it more likely that his use of regex will be std::regex or boost::regex ? IMO it is the former.
There are several good reasons to prefer boost::regex. First, the one I pointed out, you want to maintain a single code base that compiles under C++03 and C++11. Second, you want to use boost::regex's extensions that std::regex doesn't have. Third, you want predictable performance that is independent of the standard library in use.
Right. But if lib X prefers/needs to use the Boost version always, they don't have to use this mechanism.
Of course. The mechanism is completely optional.
On the other side of the coin, we have the desire to avoid use of Boost when use of standard facilities would suffice, which is real and legitimate. However, in my experience at least, this desire is only strong when you can avoid use of Boost _altogether_, which is not the case under discussion. Right, we're nowhere near having a package manager that's smart enough to avoid dependence on boost::whatever if the user tells it they have a C++11 compiler.
Boost doesn't have a package manager to begin with so I am not sure what the above means.
I guess my concerns are somewhat different from those already expressed:
* I'm not sure that this adds much over the existing macros BOOST_NO_CXX11_HDR_REGEX etc.
I am obviously using BOOST_NO_CXX11_HDR_REGEX for regex. I don't make any attempt to hide this. The current BOOST_CPP_HAS_REGEX is, I believe, a friendlier name of finding out if the C++ standard library regex is available than BOOST_NO_CXX11_HDR_REGEX but that is not the issue. On top of BOOST_NO_CXX11_HDR_REGEX I have built the simple BOOST_CPP_REGEX_HDR and BOOST_CPP_REGEX_NS macros and I seek to regularize this sort of naming for each library. It's not rocket science but I think it has value rather than everybody inventing this as a one-off situation for their own use. But of course that's my point of view as the inventor and I am biased.
* If this evolved into a more "complete" solution, then (a) It doesn't belong in Config (too many dependencies), and (b) I would worry that we repeat the mistake of Boost.TR1 - which is to say creating that particular unmaintainable monster it in the first place -just ask the author ;)
I don't think a more complete solution at the level I have specified is needed. if any further solution is needed it would be the ability, on demand, to name a non-header only library slightly differently whether or not that library is built in C++11 mode or not, and to link to the correct library name depending on C++11 mode. It seems the auto-link code in config could accomodate that for compilers that support auto-linking, but wouldn't any change have to be synced to changes in Boost Build ? For non-autolink compilers how is the library name generated ? Is it done in Boost Build or is it wholly decided by the programmer in a jam script ? I really don't know all these things but I suspect that you do and/or the Boost Build experts do.
* Folks are correct to be concerned about ABI issues: we not that long ago changed 'nix installs to install "one true binary" for each library as there was *very* strong user preference for that. Splitting into '03 and '11 binaries is IMO a significant retrograde step. If you do that expect endless newbie support requests wondering why things don't work.
First splitting binaries into C++03 and C++11 libs should only be done on demand for non-header only libraries that want to use my macro system. Secondly if the names are different the documentation explains what each variation is and it is up to the end-user to understand and use appropriately. If Boost Build automatically links the correct binary, as I believe it now does for our current naming scheme where we have different names for different variations of the same library, then the end-user should not have any problems. For any library program-wise I think it is fairly simple and I should have documented this better. If my own Boost library, called it EDS_LIB, uses my macro system for, let's say, regex, in one of its public interfaces, then any other module interfaces with EDS_LIB by hardcoding neither boost::regex or std::regex but BOOST_CPP_REGEX_NS::regex instead whenever it has to interact with my interface. Whatever compiler mode they are using, whether C++03 or C++11, it just works. Of course if they are using boost::regex everywhere else and they are forced by my macro system to use BOOST_CPP_REGEX_NS::regex and in C++11 mode that means std::regex, it's a real PITA. But that is no different than someone designing a library for C++11 use, using std::regex in a public interface, only to find out that another module compiling in C++11 mode is happily using boost::regex everywhere else but wants to use that library.
On the other hand:
* I can see a legitimate use for this as a library internal (rather like what Math does with std::tuple and boost::tuple). * The need to have different linking requirements in Boost.Build is a solved issue - just use check_target_builds to set the dependency.
So... I guess what I would like to see expressed, is what are the concrete use cases for this? What do *you* want to use it for?
I see these options realistically for Boost library developers: 1) We can continue to use public interfaces in our libraries that use other Boost libraries as the LCD, even if the C++ standard has a pretty close equivalent. Programmers compiling in C++11 mode, and inevitably there will be more as time goes on, who use the C++ standard library equivalents of Boost libraries, and inevitably there will be more using these equivalents as time goes on, may well be irritated about this situation. But if we view that as their problem and not ours, this is the obvious option. 2) We can design totally separate implementations of the same library, one to be used for C++11 and using C++ standard library equivalents in public interfaces, the other to be used for C++03 and using the equivalent Boost libraries in their public interfaces. 3) We can support our public interfaces with both the C++ standard library equivalent ( in C++11 mode ) and the Boost library equivalent, so as to accomodate end-users. 4) We can use the macro system I have created. Realistically 2) or 3) is an awful amount of work, which I as a developer would not want to do.
And finally, you are aware that there are 3 tuples available? boost::, fusion:: and std::, and they they all are slightly different? Oh and std::tr1::tuple too ;)
Yes I am aware. It is certainly permissible to say: this is my interface and if you want to use my library this is what you will use. We all do that as programmers. I just thought we could be a little more user friendly as C++11 becomes more of the norm for C++ programmers ( he ducks <g> ).
What I suspect we will see more of, is libraries becoming implementation agnostic - "give me something that looks like a tuple/thread/future/function and I'll go off and do the right thing". The latest Math code does that with tuple types, and it was a pain in the neck to get working (or possibly I was just being dense at the time), certainly the hoops you have to jump through to support that go way beyond the scope of this addition.
I hate to re-invent the wheel.
On 7 Jun 2015 at 14:16, Edward Diener wrote:
I see these options realistically for Boost library developers:
1) We can continue to use public interfaces in our libraries that use other Boost libraries as the LCD, even if the C++ standard has a pretty close equivalent. Programmers compiling in C++11 mode, and inevitably there will be more as time goes on, who use the C++ standard library equivalents of Boost libraries, and inevitably there will be more using these equivalents as time goes on, may well be irritated about this situation. But if we view that as their problem and not ours, this is the obvious option.
2) We can design totally separate implementations of the same library, one to be used for C++11 and using C++ standard library equivalents in public interfaces, the other to be used for C++03 and using the equivalent Boost libraries in their public interfaces.
3) We can support our public interfaces with both the C++ standard library equivalent ( in C++11 mode ) and the Boost library equivalent, so as to accomodate end-users.
4) We can use the macro system I have created.
Realistically 2) or 3) is an awful amount of work, which I as a developer would not want to do.
5) We can use APIBind to enable Boost library users to easily inject which dependencies a library uses from the outside, where each possible configuration of that library gets its own ABI thus ensuring that impossible or dangerous combinations fail to link and the compiler will refuse to pass ABI incompatible implementations into one another. 6) We can use APIBind to enable a Boost library to be C++ 98 compatible as part of Boost or be C++ 11 mandatory and no longer require any Boost, with an identical source code base for both config options. Also with ABI safety.
[snip] I hate to re-invent the wheel.
APIBind comes at the C++ 11 problem from the outside coming in. Yours comes from inside Boost going out. Like your solution, APIBind is proven working solution which should be better understood by the community soon at the end of July during the AFIO review, and there is a C++ Now presentation with 90 minutes on just APIBind, with plenty of valuable audience commentary by WG21 members and long time Boost community members. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/
On 6/7/2015 7:17 PM, Niall Douglas wrote:
On 7 Jun 2015 at 14:16, Edward Diener wrote:
I see these options realistically for Boost library developers:
1) We can continue to use public interfaces in our libraries that use other Boost libraries as the LCD, even if the C++ standard has a pretty close equivalent. Programmers compiling in C++11 mode, and inevitably there will be more as time goes on, who use the C++ standard library equivalents of Boost libraries, and inevitably there will be more using these equivalents as time goes on, may well be irritated about this situation. But if we view that as their problem and not ours, this is the obvious option.
2) We can design totally separate implementations of the same library, one to be used for C++11 and using C++ standard library equivalents in public interfaces, the other to be used for C++03 and using the equivalent Boost libraries in their public interfaces.
3) We can support our public interfaces with both the C++ standard library equivalent ( in C++11 mode ) and the Boost library equivalent, so as to accomodate end-users.
4) We can use the macro system I have created.
Realistically 2) or 3) is an awful amount of work, which I as a developer would not want to do.
5) We can use APIBind to enable Boost library users to easily inject which dependencies a library uses from the outside, where each possible configuration of that library gets its own ABI thus ensuring that impossible or dangerous combinations fail to link and the compiler will refuse to pass ABI incompatible implementations into one another.
6) We can use APIBind to enable a Boost library to be C++ 98 compatible as part of Boost or be C++ 11 mandatory and no longer require any Boost, with an identical source code base for both config options. Also with ABI safety.
[snip] I hate to re-invent the wheel.
APIBind comes at the C++ 11 problem from the outside coming in. Yours comes from inside Boost going out. Like your solution, APIBind is proven working solution which should be better understood by the community soon at the end of July during the AFIO review, and there is a C++ Now presentation with 90 minutes on just APIBind, with plenty of valuable audience commentary by WG21 members and long time Boost community members.
APIBind is not finished AFAICS and I do not even remotely understand the documentation you currently have for it. If others find it usable to solve this problem that is fine by me.
On 7 Jun 2015 at 22:07, Edward Diener wrote:
I hate to re-invent the wheel.
APIBind comes at the C++ 11 problem from the outside coming in. Yours comes from inside Boost going out. Like your solution, APIBind is proven working solution which should be better understood by the community soon at the end of July during the AFIO review, and there is a C++ Now presentation with 90 minutes on just APIBind, with plenty of valuable audience commentary by WG21 members and long time Boost community members.
APIBind is not finished AFAICS and I do not even remotely understand the documentation you currently have for it. If others find it usable to solve this problem that is fine by me.
A step by step explanation of how it works and feature organisation is in the slides at https://github.com/boostcon/cppnow_presentations_2015/raw/master/files /A-review-of-Cxx-11-14-only-Boost-libraries-Fiber-AFIO-DI-and-APIBind. pdf Rationale is at https://svn.boost.org/trac/boost/wiki/BestPracticeHandbook#a16.COUPLIN G:Considerallowingyourlibraryuserstodependencyinjectyourdependencieson otherlibraries What remains lacking is a step by step tutorial, but it's hardly difficult. I noticed at C++ Now I didn't find anyone didn't fully understand what was going on and how it worked, indeed Beman mentioned the same technique had been in use in C++ 11 standard library implementations for many years now. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/
On 6/8/2015 6:44 PM, Niall Douglas wrote:
On 7 Jun 2015 at 22:07, Edward Diener wrote:
I hate to re-invent the wheel.
APIBind comes at the C++ 11 problem from the outside coming in. Yours comes from inside Boost going out. Like your solution, APIBind is proven working solution which should be better understood by the community soon at the end of July during the AFIO review, and there is a C++ Now presentation with 90 minutes on just APIBind, with plenty of valuable audience commentary by WG21 members and long time Boost community members.
APIBind is not finished AFAICS and I do not even remotely understand the documentation you currently have for it. If others find it usable to solve this problem that is fine by me.
A step by step explanation of how it works and feature organisation is in the slides at https://github.com/boostcon/cppnow_presentations_2015/raw/master/files /A-review-of-Cxx-11-14-only-Boost-libraries-Fiber-AFIO-DI-and-APIBind. pdf
Rationale is at https://svn.boost.org/trac/boost/wiki/BestPracticeHandbook#a16.COUPLIN G:Considerallowingyourlibraryuserstodependencyinjectyourdependencieson otherlibraries
What remains lacking is a step by step tutorial, but it's hardly difficult. I noticed at C++ Now I didn't find anyone didn't fully understand what was going on and how it worked, indeed Beman mentioned the same technique had been in use in C++ 11 standard library implementations for many years now.
Thanks for the links. I admit I get frustrated when documentation starts off explaining to me how to use XXX without telling me what XXX is about first. If the only thing lacking is a step by step tutorial wouldn't it be better to remove the "What state is this tool in ?" in your readme.md which implies that what you are doing is not close to being finished ?
On 8 Jun 2015 at 20:16, Edward Diener wrote:
What remains lacking is a step by step tutorial, but it's hardly difficult. I noticed at C++ Now I didn't find anyone didn't fully understand what was going on and how it worked, indeed Beman mentioned the same technique had been in use in C++ 11 standard library implementations for many years now.
Thanks for the links. I admit I get frustrated when documentation starts off explaining to me how to use XXX without telling me what XXX is about first.
If the only thing lacking is a step by step tutorial wouldn't it be better to remove the "What state is this tool in ?" in your readme.md which implies that what you are doing is not close to being finished ?
I didn't want to overpromise what is there and what it can do. There is also the question of buy in. If the community buys into APIBind, then it's worth finishing it to Boost quality standards. If there isn't the interest, then it can remain as a personal private library standalone modularity toolkit only I use. tl;dr; If other people start using APIBind then I'll see plenty of reason to finish it. Otherwise I don't know if I'm solving a problem anyone else has. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/
On June 6, 2015 3:30:54 PM EDT, Edward Diener
On 6/6/2015 12:14 PM, Niall Douglas wrote:
On 5 Jun 2015 at 5:30, Edward Diener wrote:
My only real worry is the ABI problems. You need to permute the symbols being linked to avoid config mismatches colliding in an unhelpful way.
The issue as far as ABI comes down to the ability of using such a dual-mode library that is a built library and is not a header only library.
My point of view is that Boost needs to establish a way so that a library built in C++03 mode could be named slightly differently from the same library built in C++11 mode. We already have a system in place which can name a library differently depending on whether it uses the dynamic or static RTL of its implementation, or whether the library itself is a static lib or a shared lib, among other naming conventions. What I am positing for a built library is that the developer of that library should have the ability to specify that his library have a different name depending on whether it is C++03 or C++11 mode, and that this choice should work so that the correct name is used during both a
link of the library and when that library is being used by another library.
I see a problem of combinations here. If a given library depends upon several different boost/std namespace components, it will probably switch among them consistently (all Boost or all Standard Library). But if that library always chooses to use a Boost library to get some extension it provides, and that library switches things incompatibly with the first library (or doesn't switch at all), problems will ensue. These problems might be checked at runtime via version tests. The symbol check Niall mentions below is similar. At any rate, a library naming convention won't solve the problem unless there's a way to poison combining them in the wrong way.
Perhaps for each config macro have during build the library output an extern dll visible empty function with a mangled name representing the config. On use, import and use that function. This should generate link errors if one is trying to use a config against a binary not built the same way.
___ Rob (Sent from my portable computation engine)
On 6/7/2015 7:31 AM, Rob Stewart wrote:
On June 6, 2015 3:30:54 PM EDT, Edward Diener
wrote: On 6/6/2015 12:14 PM, Niall Douglas wrote:
On 5 Jun 2015 at 5:30, Edward Diener wrote:
My only real worry is the ABI problems. You need to permute the symbols being linked to avoid config mismatches colliding in an unhelpful way.
The issue as far as ABI comes down to the ability of using such a dual-mode library that is a built library and is not a header only library.
My point of view is that Boost needs to establish a way so that a library built in C++03 mode could be named slightly differently from the same library built in C++11 mode. We already have a system in place which can name a library differently depending on whether it uses the dynamic or static RTL of its implementation, or whether the library itself is a static lib or a shared lib, among other naming conventions. What I am positing for a built library is that the developer of that library should have the ability to specify that his library have a different name depending on whether it is C++03 or C++11 mode, and that this choice should work so that the correct name is used during both a
link of the library and when that library is being used by another library.
I see a problem of combinations here. If a given library depends upon several different boost/std namespace components, it will probably switch among them consistently (all Boost or all Standard Library). But if that library always chooses to use a Boost library to get some extension it provides, and that library switches things incompatibly with the first library (or doesn't switch at all), problems will ensue.
If my interface to my library uses my macro system for a particular Boost library, and you interface to my library then you should use the same macro system for that interface. But outside that interface you can use what you want. This is absolutely no different from this situation: you are compiling in C++11 mode and using std::xxx and some Boost library uses boost::xxx instead in its interface. What do you do ? I honestly don't mind and do understand the opinion that a Boost library should always use another Boost library rather than its C++ standard library equivalent in its public interfaces as the LCD that will work with C++03 and C++11. I just don't think this scales well as more C++ programmers use C++11 and find themselves using the C++ standard libraries in their code. My macro system is an attempt to accomodate that situation in C++'s future, which I view as inevitable.
These problems might be checked at runtime via version tests. The symbol check Niall mentions below is similar. At any rate, a library naming convention won't solve the problem unless there's a way to poison combining them in the wrong way.
Perhaps for each config macro have during build the library output an extern dll visible empty function with a mangled name representing the config. On use, import and use that function. This should generate link errors if one is trying to use a config against a binary not built the same way.
Le 05/06/15 09:41, John Maddock a écrit :
There is a pull-request for Config to provide support for switching between boost:: and std:: library equivalents: https://github.com/boostorg/config/pull/63
My questions are:
* Is this the right approach? And, * Is Boost.Config the right place for it?
This PR makes Boost.Config depend on all the related Boost libraries creating a whole cycle and modularity will be broken. It would suggest to have some kind of Boost.Std library with different versions c++11/c++14 and why not TSs. However the concerned libraries couldn't use this library without adding cycles :( Having a sub-library for each file Boost.Std/Regex would make it possible for a Boost library to use these sub-libraries without adding cycles. An alternative is to add these files in the concerned libraries, e.g. boost/regex/std/regex.hpp Vicente
On 07.06.2015 11:39, Vicente J. Botet Escriba wrote:
Le 05/06/15 09:41, John Maddock a écrit :
There is a pull-request for Config to provide support for switching between boost:: and std:: library equivalents: https://github.com/boostorg/config/pull/63
My questions are:
* Is this the right approach? And, * Is Boost.Config the right place for it?
This PR makes Boost.Config depend on all the related Boost libraries creating a whole cycle and modularity will be broken.
These headers don't add a dependency since they don't include headers of the related libraries. They only define macros.
On 6/7/2015 4:39 AM, Vicente J. Botet Escriba wrote:
Le 05/06/15 09:41, John Maddock a écrit :
There is a pull-request for Config to provide support for switching between boost:: and std:: library equivalents: https://github.com/boostorg/config/pull/63
My questions are:
* Is this the right approach? And, * Is Boost.Config the right place for it?
This PR makes Boost.Config depend on all the related Boost libraries creating a whole cycle and modularity will be broken.
The PR just adds macros. It does not add dependencies to Boost.config.
It would suggest to have some kind of Boost.Std library with different versions c++11/c++14 and why not TSs.
However the concerned libraries couldn't use this library without adding cycles :(
Having a sub-library for each file Boost.Std/Regex would make it possible for a Boost library to use these sub-libraries without adding cycles.
An alternative is to add these files in the concerned libraries, e.g. boost/regex/std/regex.hpp
participants (10)
-
Andrey Semashev
-
Bjorn Reese
-
Edward Diener
-
John Maddock
-
Niall Douglas
-
Peter Dimov
-
Rob Stewart
-
Robert Ramey
-
Sylvester-Bradley, Gareth
-
Vicente J. Botet Escriba