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.