|
Boost : |
Subject: Re: [boost] [Config] Support for switching between std:: and boost:: equivalents.
From: Edward Diener (eldiener_at_[hidden])
Date: 2015-06-06 16:54:22
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 <boost/config/cpp/regex.hpp>
#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 <boost/config/cpp/regex.hpp>
#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 )
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.
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.
>
> 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 ?
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk