Curiousity question
I would like to ask a design question for any Boost developers or anyone on this mailing list who might care to answer. You are designing or working on a library, perhaps for Boost, perhaps for fun, and part of the design of the library has some public functionality taking a shared pointer as input. You: 1) Use boost::shared_ptr 2) Use std::shared_ptr 3) Use both boost::shared_ptr and std::shared_ptr with the same functionality 4) Use neither, you roll your own shared pointer-like functionality 5) You don't lke shared pointers and use raw pointers instead I really am curious about this. I haven't put any limitation on your library or made any presumption on who your library is for, on purpose. Thanks for anyone answering !
On Wed, Oct 12, 2016 at 6:58 PM, Edward Diener
You are designing or working on a library, perhaps for Boost, perhaps for fun, and part of the design of the library has some public functionality taking a shared pointer as input. You: ... 2) Use std::shared_ptr
I would use std::shared_ptr and I'll answer the broader version of your question. For my libraries, I assume C++11. Its too much work to try to support older compilers. There are so many features and advantages to having C++11 as the minimum language support that it is a very logical choice to require it.
On 10/12/2016 7:09 PM, Vinnie Falco wrote:
On Wed, Oct 12, 2016 at 6:58 PM, Edward Diener
wrote: You are designing or working on a library, perhaps for Boost, perhaps for fun, and part of the design of the library has some public functionality taking a shared pointer as input. You: ... 2) Use std::shared_ptr
I would use std::shared_ptr and I'll answer the broader version of your question.
For my libraries, I assume C++11. Its too much work to try to support older compilers. There are so many features and advantages to having C++11 as the minimum language support that it is a very logical choice to require it.
Your assumption, of course is that any C++11 compiler implementation supports std::shared_ptr. Fair enough. Thanks !
On 12.10.2016 18:58, Edward Diener wrote:
I would like to ask a design question for any Boost developers or anyone on this mailing list who might care to answer.
You are designing or working on a library, perhaps for Boost, perhaps for fun, and part of the design of the library has some public functionality taking a shared pointer as input. You:
1) Use boost::shared_ptr 2) Use std::shared_ptr 3) Use both boost::shared_ptr and std::shared_ptr with the same functionality 4) Use neither, you roll your own shared pointer-like functionality 5) You don't lke shared pointers and use raw pointers instead
I really am curious about this. I haven't put any limitation on your library or made any presumption on who your library is for, on purpose. Thanks for anyone answering !
At this point in time (with GCC 6.2 as my default compiler in my development environment), I'd use std::shared_ptr, and fall back to boost::shared_ptr for environments without C++11 support. (In practice it's often the other way around. Consider Boost.Python: it has been supporting boost::shared_ptr for a long time, and I just now managed to add support for std::shared_ptr. I expect to eventually deprecate support for boost::shared_ptr, but that will still take a few years.) Stefan -- ...ich hab' noch einen Koffer in Berlin...
On 10/12/2016 7:17 PM, Stefan Seefeld wrote:
On 12.10.2016 18:58, Edward Diener wrote:
I would like to ask a design question for any Boost developers or anyone on this mailing list who might care to answer.
You are designing or working on a library, perhaps for Boost, perhaps for fun, and part of the design of the library has some public functionality taking a shared pointer as input. You:
1) Use boost::shared_ptr 2) Use std::shared_ptr 3) Use both boost::shared_ptr and std::shared_ptr with the same functionality 4) Use neither, you roll your own shared pointer-like functionality 5) You don't lke shared pointers and use raw pointers instead
I really am curious about this. I haven't put any limitation on your library or made any presumption on who your library is for, on purpose. Thanks for anyone answering !
At this point in time (with GCC 6.2 as my default compiler in my development environment), I'd use std::shared_ptr, and fall back to boost::shared_ptr for environments without C++11 support.
How would you fall back to support boost::shared_ptr ?
(In practice it's often the other way around. Consider Boost.Python: it has been supporting boost::shared_ptr for a long time, and I just now managed to add support for std::shared_ptr. I expect to eventually deprecate support for boost::shared_ptr, but that will still take a few years.)
So your interface(s) need to support both in the meantime ?
On 12.10.2016 20:20, Edward Diener wrote:
On 10/12/2016 7:17 PM, Stefan Seefeld wrote:
At this point in time (with GCC 6.2 as my default compiler in my development environment), I'd use std::shared_ptr, and fall back to boost::shared_ptr for environments without C++11 support.
How would you fall back to support boost::shared_ptr ?
With something as simple as: #if __cplusplus >= 201103L // use std::shared_ptr ... #else // use boost::shared_ptr ... #endif
(In practice it's often the other way around. Consider Boost.Python: it has been supporting boost::shared_ptr for a long time, and I just now managed to add support for std::shared_ptr. I expect to eventually deprecate support for boost::shared_ptr, but that will still take a few years.)
So your interface(s) need to support both in the meantime ?
Yes. Stefan -- ...ich hab' noch einen Koffer in Berlin...
On 10/12/2016 8:40 PM, Stefan Seefeld wrote:
On 12.10.2016 20:20, Edward Diener wrote:
On 10/12/2016 7:17 PM, Stefan Seefeld wrote:
At this point in time (with GCC 6.2 as my default compiler in my development environment), I'd use std::shared_ptr, and fall back to boost::shared_ptr for environments without C++11 support.
How would you fall back to support boost::shared_ptr ?
With something as simple as:
#if __cplusplus >= 201103L // use std::shared_ptr ... #else // use boost::shared_ptr ... #endif
Wouldn't you need to duplicate the above every time you are using shared pointers ?
(In practice it's often the other way around. Consider Boost.Python: it has been supporting boost::shared_ptr for a long time, and I just now managed to add support for std::shared_ptr. I expect to eventually deprecate support for boost::shared_ptr, but that will still take a few years.)
So your interface(s) need to support both in the meantime ?
Yes.
OK, Thanks !
On 12.10.2016 21:19, Edward Diener wrote:
On 10/12/2016 8:40 PM, Stefan Seefeld wrote:
On 12.10.2016 20:20, Edward Diener wrote:
On 10/12/2016 7:17 PM, Stefan Seefeld wrote:
At this point in time (with GCC 6.2 as my default compiler in my development environment), I'd use std::shared_ptr, and fall back to boost::shared_ptr for environments without C++11 support.
How would you fall back to support boost::shared_ptr ?
With something as simple as:
#if __cplusplus >= 201103L // use std::shared_ptr ... #else // use boost::shared_ptr ... #endif
Wouldn't you need to duplicate the above every time you are using shared pointers ?
That depends on the granularity of the conditional block (something between conditionalizing a single token and including an entire header). What works best depends on the specific context. In Boost.Python there aren't that many places in need of conditionalizing. Most code is so generic it doesn't even know or care whether it's passing shared pointers around. Stefan -- ...ich hab' noch einen Koffer in Berlin...
On 10/12/2016 9:29 PM, Stefan Seefeld wrote:
On 12.10.2016 21:19, Edward Diener wrote:
On 10/12/2016 8:40 PM, Stefan Seefeld wrote:
On 12.10.2016 20:20, Edward Diener wrote:
On 10/12/2016 7:17 PM, Stefan Seefeld wrote:
At this point in time (with GCC 6.2 as my default compiler in my development environment), I'd use std::shared_ptr, and fall back to boost::shared_ptr for environments without C++11 support.
How would you fall back to support boost::shared_ptr ?
With something as simple as:
#if __cplusplus >= 201103L // use std::shared_ptr ... #else // use boost::shared_ptr ... #endif
Wouldn't you need to duplicate the above every time you are using shared pointers ?
That depends on the granularity of the conditional block (something between conditionalizing a single token and including an entire header). What works best depends on the specific context.
In Boost.Python there aren't that many places in need of conditionalizing. Most code is so generic it doesn't even know or care whether it's passing shared pointers around.
OK, Thanks for the explanation.
Stefan
On 13/10/2016 11:58, Edward Diener wrote:
I would like to ask a design question for any Boost developers or anyone on this mailing list who might care to answer.
You are designing or working on a library, perhaps for Boost, perhaps for fun, and part of the design of the library has some public functionality taking a shared pointer as input. You:
1) Use boost::shared_ptr 2) Use std::shared_ptr 3) Use both boost::shared_ptr and std::shared_ptr with the same functionality 4) Use neither, you roll your own shared pointer-like functionality 5) You don't lke shared pointers and use raw pointers instead
I really am curious about this. I haven't put any limitation on your library or made any presumption on who your library is for, on purpose.
If I'm writing a small library/program that doesn't need Boost for something else, then I'll use std::shared_ptr. Otherwise, I'll use boost::shared_ptr, except where required to use std::shared_ptr by existing interfaces. (Why? Because boost::shared_ptr is better. It has shared_from_raw and a few other such convenience features.)
On 10/12/2016 8:06 PM, Gavin Lambert wrote:
On 13/10/2016 11:58, Edward Diener wrote:
I would like to ask a design question for any Boost developers or anyone on this mailing list who might care to answer.
You are designing or working on a library, perhaps for Boost, perhaps for fun, and part of the design of the library has some public functionality taking a shared pointer as input. You:
1) Use boost::shared_ptr 2) Use std::shared_ptr 3) Use both boost::shared_ptr and std::shared_ptr with the same functionality 4) Use neither, you roll your own shared pointer-like functionality 5) You don't lke shared pointers and use raw pointers instead
I really am curious about this. I haven't put any limitation on your library or made any presumption on who your library is for, on purpose.
If I'm writing a small library/program that doesn't need Boost for something else, then I'll use std::shared_ptr.
Are you assuming that programmers using your small library compiler with c++11 support ?
Otherwise, I'll use boost::shared_ptr, except where required to use std::shared_ptr by existing interfaces.
So if existing interfaces already used std::shared_ptr you'd keep them like that, else for any new shared pointer interfaces you would use boost::shared_ptr ?
(Why? Because boost::shared_ptr is better. It has shared_from_raw and a few other such convenience features.)
On 13/10/2016 13:24, Edward Diener wrote:
Are you assuming that programmers using your small library compiler with c++11 support ?
Mostly I'm writing apps, or libraries for use within my organisation,
not really for public consumption. So based on the intended target
app/environment I already know whether it supports C++11 or not and can
pick accordingly.
Perhaps I'm not the intended audience of your question in that regard. :)
Not so much with shared_ptr (since boost::shared_ptr is a reasonable
default for the dual case anyway), but in some cases where something
needs to be used in both environments I'll put in some custom
redirection eg:
#if some_detection_magic
#include <atomic>
namespace my_atomic { using std::atomic; }
#elif some_other_detection_magic
#include
Otherwise, I'll use boost::shared_ptr, except where required to use std::shared_ptr by existing interfaces.
So if existing interfaces already used std::shared_ptr you'd keep them like that, else for any new shared pointer interfaces you would use boost::shared_ptr ?
If my code depends on something that uses std::shared_ptr then of course I'll use std::shared_ptr in the downwards-facing interfaces with that. But I will prefer boost::shared_ptr for any upwards-facing interfaces unless there's some compelling reason not to use it (such as not otherwise requiring a dependency on Boost).
On 10/12/2016 9:09 PM, Gavin Lambert wrote:
On 13/10/2016 13:24, Edward Diener wrote:
Are you assuming that programmers using your small library compiler with c++11 support ?
Mostly I'm writing apps, or libraries for use within my organisation, not really for public consumption. So based on the intended target app/environment I already know whether it supports C++11 or not and can pick accordingly.
Perhaps I'm not the intended audience of your question in that regard. :)
I was just asking as a general question to see what others do. Any answers regarding your choice is interesting and valuable to me.
Not so much with shared_ptr (since boost::shared_ptr is a reasonable default for the dual case anyway), but in some cases where something needs to be used in both environments I'll put in some custom redirection eg:
#if some_detection_magic #include <atomic> namespace my_atomic { using std::atomic; } #elif some_other_detection_magic #include
namespace my_atomic { using boost::atomic; } #elif some_fallback_is_available ... some custom implementation ... #else #error Cannot find an atomic implementation. #endif
Yes, this I understand. My cxx_dual library basically does the above but in a syntactically smoother manner, while assuming that the Boost side is always available so no "Cannot find an atomic implementation" will ever occur there.
And then my code will use only my_atomic::atomic instead. Obviously this is ABI incompatible whenever the magic detects differently, so it makes it harder to provide pre-built binaries, but it's great for source compatibility.
Understood.
In fact half the time I wonder if I should refactor code so that it never uses the std:: or boost:: namespaces directly and always import things into custom namespaces like this, such that it's trivial to swap out all uses of a given type with an alternate implementation, either from a separate library or with a custom wrapper. (Sometimes I have moments where I want to swap a custom allocator into all std::vectors, for example, which is easier if everything actually uses a custom typedef/alias.)
A namespace alias also works nicely. That's what cxx_dual uses. It's also much easier to encode into the process of dual implementations.
Haven't quite gone that far yet myself though, though I know that your cxx_dual library and Niall's similar library are along those lines.
The impetus for cxx_dual is that I was ( and still am ) working on a library where shared pointers and function callables are part of some public interfaces. So I was trying to decide, do I use boost::shared_ptr or std::shared_ptr, do I use boost::function or std::function ? And I had some answers, but whatever it was I felt I was sure to run into a potential end-user of my library who would feel, based on his compiler implementation, compiler support for C++11, compiler options, OS for which he was using my library, that whatever I chose would be wrong for him. Of course like most programmers I could simply say, these are my choices and if they don't correspond to what you are otherwise using if you use my library, it is up to you to adjust. My OP is an effort to see how other programmers involved with Boost think about this.
Otherwise, I'll use boost::shared_ptr, except where required to use std::shared_ptr by existing interfaces.
So if existing interfaces already used std::shared_ptr you'd keep them like that, else for any new shared pointer interfaces you would use boost::shared_ptr ?
If my code depends on something that uses std::shared_ptr then of course I'll use std::shared_ptr in the downwards-facing interfaces with that. But I will prefer boost::shared_ptr for any upwards-facing interfaces unless there's some compelling reason not to use it (such as not otherwise requiring a dependency on Boost).
The end-user of your library, especially if it is meant for public consumption, might find it odd <g> that some interfaces use std::shared_ptr and others use boost::shared_ptr. Even more so if he is using one or the other of the two consistently throughout his own usage of your library in whatever executable or library he is working on. But I understand why you would prefer your own way. As long as you document what should be used it is easy enough for the end-user of your library to adapt successfully.
On 13/10/2016 15:04, Edward Diener wrote:
The end-user of your library, especially if it is meant for public consumption, might find it odd <g> that some interfaces use std::shared_ptr and others use boost::shared_ptr. Even more so if he is using one or the other of the two consistently throughout his own usage of your library in whatever executable or library he is working on. But I understand why you would prefer your own way. As long as you document what should be used it is easy enough for the end-user of your library to adapt successfully.
Typically I'll use a typedef in any public API anyway, such that consumers will just use FooPtr (or auto) and thus never need to type shared_ptr themselves. Or I'll use a handle/body pimpl idiom so that the only shared_ptrs they see are the single private member of the handle type, and again they don't need to see them. So in that regard, they shouldn't need to care which one I chose to use.
On 10/12/2016 10:27 PM, Gavin Lambert wrote:
On 13/10/2016 15:04, Edward Diener wrote:
The end-user of your library, especially if it is meant for public consumption, might find it odd <g> that some interfaces use std::shared_ptr and others use boost::shared_ptr. Even more so if he is using one or the other of the two consistently throughout his own usage of your library in whatever executable or library he is working on. But I understand why you would prefer your own way. As long as you document what should be used it is easy enough for the end-user of your library to adapt successfully.
Typically I'll use a typedef in any public API anyway, such that consumers will just use FooPtr (or auto) and thus never need to type shared_ptr themselves.
Or I'll use a handle/body pimpl idiom so that the only shared_ptrs they see are the single private member of the handle type, and again they don't need to see them.
So in that regard, they shouldn't need to care which one I chose to use.
These are interesting ideas. Thanks !
On 12 Oct 2016 at 22:04, Edward Diener wrote:
Haven't quite gone that far yet myself though, though I know that your cxx_dual library and Niall's similar library are along those lines.
The impetus for cxx_dual is that I was ( and still am ) working on a library where shared pointers and function callables are part of some public interfaces. So I was trying to decide, do I use boost::shared_ptr or std::shared_ptr, do I use boost::function or std::function ? And I had some answers, but whatever it was I felt I was sure to run into a potential end-user of my library who would feel, based on his compiler implementation, compiler support for C++11, compiler options, OS for which he was using my library, that whatever I chose would be wrong for him. Of course like most programmers I could simply say, these are my choices and if they don't correspond to what you are otherwise using if you use my library, it is up to you to adjust. My OP is an effort to see how other programmers involved with Boost think about this.
Firstly Edward, you've done a really nice job with cxx_dual. Far more polished than my effort, which I effectively stopped work upon after it was clear after my C++ Now 2015 presentation of it showed there was little interest in such a facility from Boost people. I also am finding these responses very interesting, and thank you for asking the question, indeed you preempted me asking the same question. The responses confirmed my increasing suspicion that people are either rolling their own on the spot or else just assuming C++ 11. Not enough people want a formal framework for switching between STL 11 implementations. BindLib is now Boost-lite, and instead of focusing effort on providing code to shim between standards implementations I am now focusing effort on a new collection of standards aspiring C++ libraries based on the feedback yielded from the informal meetings I ran during CppCon 2016 (and which were minuted, and those minutes were distributed to those who attended). The new collection obviously includes all my own libraries, but I wouldn't recommend anyone else use it yet, it's too rough because it's using bleeding edge cmake and other tooling (e.g. it needs trunk LLVM 4.0) as well as bleeding edge C++ 17. I'm hoping to add a year of maturity to it first, and then open it up to anyone else who wants to add their libraries. I should emphasise that Boost lite is not an alternative to Boost, more a staging ground for new libraries. A library should be able to coexist in both collections, and my aim is that Boost lite's many perhaps too bleeding edge facilities will greatly ease initial new C++ library development as a half way house to entering the Boost review queue and later entry into Boost. The idea is that the new tooling can automate a great deal of development tedium away, but the swap is that the C++ library has extremely strict requirements placed on exactly how it's organised and laid out to the extent that you'd have a lot of refactoring needed to bring in an existing library. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/
On 10/13/2016 7:34 AM, Niall Douglas wrote:
On 12 Oct 2016 at 22:04, Edward Diener wrote:
Haven't quite gone that far yet myself though, though I know that your cxx_dual library and Niall's similar library are along those lines.
The impetus for cxx_dual is that I was ( and still am ) working on a library where shared pointers and function callables are part of some public interfaces. So I was trying to decide, do I use boost::shared_ptr or std::shared_ptr, do I use boost::function or std::function ? And I had some answers, but whatever it was I felt I was sure to run into a potential end-user of my library who would feel, based on his compiler implementation, compiler support for C++11, compiler options, OS for which he was using my library, that whatever I chose would be wrong for him. Of course like most programmers I could simply say, these are my choices and if they don't correspond to what you are otherwise using if you use my library, it is up to you to adjust. My OP is an effort to see how other programmers involved with Boost think about this.
Firstly Edward, you've done a really nice job with cxx_dual. Far more polished than my effort, which I effectively stopped work upon after it was clear after my C++ Now 2015 presentation of it showed there was little interest in such a facility from Boost people.
I appreciate the nice words.
I also am finding these responses very interesting, and thank you for asking the question, indeed you preempted me asking the same question. The responses confirmed my increasing suspicion that people are either rolling their own on the spot or else just assuming C++ 11. Not enough people want a formal framework for switching between STL 11 implementations.
Yes I agree with you. The lack of interest in even seeing what cxx_dual was about or trying it out, even when I attempted to make it as easy as possible for those who dislike seeing macros in their own code, does not really personally bother me since I write software for my own pleasure or practical use unless I am being paid to do it as a consultant. But it started me thinking about what other people do when they have to decide about using a Boost implementation of some library versus a C++ standard implementation of the same general library, since evidently cxx_dual is not the answer for them.
BindLib is now Boost-lite, and instead of focusing effort on providing code to shim between standards implementations I am now focusing effort on a new collection of standards aspiring C++ libraries based on the feedback yielded from the informal meetings I ran during CppCon 2016 (and which were minuted, and those minutes were distributed to those who attended). The new collection obviously includes all my own libraries, but I wouldn't recommend anyone else use it yet, it's too rough because it's using bleeding edge cmake and other tooling (e.g. it needs trunk LLVM 4.0) as well as bleeding edge C++ 17. I'm hoping to add a year of maturity to it first, and then open it up to anyone else who wants to add their libraries.
I should emphasise that Boost lite is not an alternative to Boost, more a staging ground for new libraries. A library should be able to coexist in both collections, and my aim is that Boost lite's many perhaps too bleeding edge facilities will greatly ease initial new C++ library development as a half way house to entering the Boost review queue and later entry into Boost. The idea is that the new tooling can automate a great deal of development tedium away, but the swap is that the C++ library has extremely strict requirements placed on exactly how it's organised and laid out to the extent that you'd have a lot of refactoring needed to bring in an existing library.
I personally believe that programmers will write libraries for C++11+ ( C++11, C++14, C++17 ) when the facilites of C++11+ are found to be useful for whatever programming may be needed for their library. I don't believe that any programmer can, or should, use whatever is the latest and greatest unless it provides an advantage for them. With that said any facility that makes it easier for programmers to write code that can be used by other programmers targeting C++11+ can be valuable. So go for it. I have always believed that a library targeted for C++11+ should be accepted into Boost if it is a worthy library, even if it cannot be used by programmers not compiling with C++11+. That has already happened with some Boost libraries and I see it as beneficial for showing what C++11+ can do.
Edward Diener wrote:
The lack of interest in even seeing what cxx_dual was about or trying it out, even when I attempted to make it as easy as possible for those who dislike seeing macros in their own code, does not really personally bother me since I write software for my own pleasure or practical use unless I am being paid to do it as a consultant.
The basic issue with a Boost library that allows one to switch between Boost and standard components is this: the usual motivation for using a standard component when available is to avoid a dependency on Boost. But if you don't have Boost, you also don't have the Boost library that would allow you to switch.
On 10/13/2016 10:31 AM, Peter Dimov wrote:
Edward Diener wrote:
The lack of interest in even seeing what cxx_dual was about or trying it out, even when I attempted to make it as easy as possible for those who dislike seeing macros in their own code, does not really personally bother me since I write software for my own pleasure or practical use unless I am being paid to do it as a consultant.
The basic issue with a Boost library that allows one to switch between Boost and standard components is this: the usual motivation for using a standard component when available is to avoid a dependency on Boost. But if you don't have Boost, you also don't have the Boost library that would allow you to switch.
Good point ! I probably did not make the argument well enough that even when you have Boost you might prefer the C++ standard equivalent to avoid the Boost dependency. In other words, "having Boost" and "depending on Boost", for a particular library, are conceptually two different things, at least in my mind. Also the decision-making process in cxx_dual depends only on Boost Config. Other optional macro support in cxx_dual depends on PP and VMD. Tests depend on some other Boost libraries even when Boost is not chosen as a dual library. I can probably eleiminate the latter ( except for lightweight test ) if I want to.
On Thu, Oct 13, 2016 at 10:54 AM, Edward Diener
...even when you have Boost you might prefer the C++ standard equivalent to avoid the Boost dependency.
There is a greater cost to using Boost types over their C++ equivalent. They often differ in small ways. boost::optional, boost::posix_time, and boost::shared_ptr come to mind, there are others. When writing code you can assume that a reader will know and understand C++ standard library types (since they are... standard). The same cannot be said about the corresponding Boost types. Admittedly this difference is sometimes slight but it is still present. For this reason, a standard library type almost always has an advantage even when the Boost type offers improved functionality; standard library types are what all C++ programmers know.
On 2016-10-13 17:09, Vinnie Falco wrote:
On Thu, Oct 13, 2016 at 10:54 AM, Edward Diener
wrote: ...even when you have Boost you might prefer the C++ standard equivalent to avoid the Boost dependency.
There is a greater cost to using Boost types over their C++ equivalent. They often differ in small ways. boost::optional, boost::posix_time, and boost::shared_ptr come to mind, there are others.
When writing code you can assume that a reader will know and understand C++ standard library types (since they are... standard). The same cannot be said about the corresponding Boost types. Admittedly this difference is sometimes slight but it is still present.
For this reason, a standard library type almost always has an advantage even when the Boost type offers improved functionality; standard library types are what all C++ programmers know.
Thanks Vinnie, you are writing much better I have been trying to write. I also see a bigger problem regarding the "bigger outlook". As a library maintainer of a boost library, would I rather have to support the boost type or the std type? It would be weird if my library would depend on std::posix_time but could not work with boost::posix_time. Sometimes, because of the subtle change in semantics, I have to choose one. Giving your argument I would choose std::posix_time which would make my own library semantically incompatible to boost. If I follow the ideal of "everything in boost should work together", then I would not fit well in the C++11 world any more. There was a while back a longer thread about having a "new" boost which cleans up on its old outdated libraries and I am now thinking that this here would be a rather good argument of doing such a change. In a first step one might say that everything in boost should work well with the std types (as long as there are no very good reasons not to do so), while the boost duplicates would become deprecated. In a subsequent change a boost/compat would be introduced with the sole purpose of adding support for libraries that are used in boost but are broken on compilers supported by boost (e.g. std::ref where it is broken). When all broken compilers are faded out, the compat part is removed so that at some point nothing is left. While this would introduce a lot of work, it would, in the long run free boost from the dilemma above. Best, Oswin
On 10/13/2016 11:09 AM, Vinnie Falco wrote:
On Thu, Oct 13, 2016 at 10:54 AM, Edward Diener
wrote: ...even when you have Boost you might prefer the C++ standard equivalent to avoid the Boost dependency.
There is a greater cost to using Boost types over their C++ equivalent. They often differ in small ways. boost::optional, boost::posix_time, and boost::shared_ptr come to mind, there are others.
When writing code you can assume that a reader will know and understand C++ standard library types (since they are... standard). The same cannot be said about the corresponding Boost types. Admittedly this difference is sometimes slight but it is still present.
For this reason, a standard library type almost always has an advantage even when the Boost type offers improved functionality; standard library types are what all C++ programmers know.
The default in my cxx_dual library is to use the C++ standard library, when it is available, over the Boost equivalent based on the dependency consideration. Your opinion only justifies that default even more. My OP was basically an attempt to ask how others decide and how they program their decision.
On Thu, 13 Oct 2016 at 10:32 Peter Dimov
Edward Diener wrote:
The basic issue with a Boost library that allows one to switch between Boost and standard components is this: the usual motivation for using a standard component when available is to avoid a dependency on Boost. But if you don't have Boost, you also don't have the Boost library that would allow you to switch.
There are two other motivations I've run into in the wild. a. To depend on less of boost for compile time reasons. The standard library equivalents on a given platform typically compile faster than the boost equivalents because they have less machinery thanks to only having to worry about a single platform. I say typically because it's not this simple since boost headers can be included in a more piecemeal fashion which can be used to optimize, but in practice, it holds. b. Some platforms don't have a boost implementation of things like threads, so its useful to be able to use the vendor supplied std versions in those cases. -- chris
On 10/13/2016 11:49 AM, Chris Glover wrote:
On Thu, 13 Oct 2016 at 10:32 Peter Dimov
wrote: Edward Diener wrote:
The basic issue with a Boost library that allows one to switch between Boost and standard components is this: the usual motivation for using a standard component when available is to avoid a dependency on Boost. But if you don't have Boost, you also don't have the Boost library that would allow you to switch.
You quoted me for the above but it should be Peter Dimov. I did author the OP.
There are two other motivations I've run into in the wild.
a. To depend on less of boost for compile time reasons. The standard library equivalents on a given platform typically compile faster than the boost equivalents because they have less machinery thanks to only having to worry about a single platform. I say typically because it's not this simple since boost headers can be included in a more piecemeal fashion which can be used to optimize, but in practice, it holds.
b. Some platforms don't have a boost implementation of things like threads, so its useful to be able to use the vendor supplied std versions in those cases.
As an adjunct to your second point some compilers don't even support C++ standard versions of Boost equivalent libraries even when compiling in C++11 mode. When I created cxx_dual it was not so much because I thought that a Boost distribution was an unwanted burden for programmers or programming groups to have on their hard disks, but more because I thought that programmers would not want to use a Boost library if its C++ standard equivalent library was available to be used.
Hi, On 2016-10-13 00:58, Edward Diener wrote:
I would like to ask a design question for any Boost developers or anyone on this mailing list who might care to answer.
You are designing or working on a library, perhaps for Boost, perhaps for fun, and part of the design of the library has some public functionality taking a shared pointer as input. You: [...] 2) Use std::shared_ptr
From my point of view, this is the best option and I would go so far as to say that this holds for almost all boost libraries that were included in c++11. My main argument is that it makes it easier for new projects to introduce boost, as it fits better into the c++11 environment. I agree that for most libraries, the boost version are a bit better or have a few more features, but for me this does not outweigh the cost of incompatbility with standard c++11 coding habits. I can not force a project to adopt all of boost even if they are only interested in a tiny fragment of it. Otherwise, if there are deep concerns about compatibility with boost, i would try to introduce a policy or simply use template arguments which just assume it is a shared_ptr of some kind. Best, Oswin
On 10/13/2016 4:21 AM, Oswin Krause wrote:
Hi,
On 2016-10-13 00:58, Edward Diener wrote:
I would like to ask a design question for any Boost developers or anyone on this mailing list who might care to answer.
You are designing or working on a library, perhaps for Boost, perhaps for fun, and part of the design of the library has some public functionality taking a shared pointer as input. You: [...] 2) Use std::shared_ptr
From my point of view, this is the best option and I would go so far as to say that this holds for almost all boost libraries that were included in c++11. My main argument is that it makes it easier for new projects to introduce boost, as it fits better into the c++11 environment. I agree that for most libraries, the boost version are a bit better or have a few more features, but for me this does not outweigh the cost of incompatbility with standard c++11 coding habits. I can not force a project to adopt all of boost even if they are only interested in a tiny fragment of it.
I gather then that your library is for programmers using C+11 on up.
Otherwise, if there are deep concerns about compatibility with boost, i would try to introduce a policy or simply use template arguments which just assume it is a shared_ptr of some kind.
In other words you would roll your own class template ?
Best, Oswin
Hi,
I gather then that your library is for programmers using C+11 on up.
Well, prior to C++11 there is not such a question due to a lack of std::shared_ptr, so yes, solution 1) assumes C++11. For a new library I would take the route that is easiest to maintain in the years to come.
On 13/10/2016 22:42, Oswin Krause wrote:
Well, prior to C++11 there is not such a question due to a lack of std::shared_ptr, so yes, solution 1) assumes C++11. For a new library I would take the route that is easiest to maintain in the years to come.
Actually std::tr1::shared_ptr or stdext::shared_ptr (variously) has been in many CRTs for many years before C++11. Though it didn't catch on as much.
On 10/13/16 01:58, Edward Diener wrote:
I would like to ask a design question for any Boost developers or anyone on this mailing list who might care to answer.
You are designing or working on a library, perhaps for Boost, perhaps for fun, and part of the design of the library has some public functionality taking a shared pointer as input. You:
1) Use boost::shared_ptr 2) Use std::shared_ptr 3) Use both boost::shared_ptr and std::shared_ptr with the same functionality 4) Use neither, you roll your own shared pointer-like functionality 5) You don't lke shared pointers and use raw pointers instead
I really am curious about this. I haven't put any limitation on your library or made any presumption on who your library is for, on purpose. Thanks for anyone answering !
Depends on the target. If I can rely on C++11 features being available in the project then I use std::shared_ptr. Otherwise I use boost::shared_ptr. Both times unconditionally, i.e. no auto-detection stuff.
On 10/13/16 12:14, Andrey Semashev wrote:
On 10/13/16 01:58, Edward Diener wrote:
I would like to ask a design question for any Boost developers or anyone on this mailing list who might care to answer.
You are designing or working on a library, perhaps for Boost, perhaps for fun, and part of the design of the library has some public functionality taking a shared pointer as input. You:
1) Use boost::shared_ptr 2) Use std::shared_ptr 3) Use both boost::shared_ptr and std::shared_ptr with the same functionality 4) Use neither, you roll your own shared pointer-like functionality 5) You don't lke shared pointers and use raw pointers instead
I really am curious about this. I haven't put any limitation on your library or made any presumption on who your library is for, on purpose. Thanks for anyone answering !
Depends on the target. If I can rely on C++11 features being available in the project then I use std::shared_ptr. Otherwise I use boost::shared_ptr. Both times unconditionally, i.e. no auto-detection stuff.
I should also say that I find myself often using boost::intrusive_ptr instead of either std::shared_ptr or boost::shared_ptr but I'm not sure that's the answer you're looking for.
On 10/13/2016 5:43 AM, Andrey Semashev wrote:
On 10/13/16 12:14, Andrey Semashev wrote:
On 10/13/16 01:58, Edward Diener wrote:
I would like to ask a design question for any Boost developers or anyone on this mailing list who might care to answer.
You are designing or working on a library, perhaps for Boost, perhaps for fun, and part of the design of the library has some public functionality taking a shared pointer as input. You:
1) Use boost::shared_ptr 2) Use std::shared_ptr 3) Use both boost::shared_ptr and std::shared_ptr with the same functionality 4) Use neither, you roll your own shared pointer-like functionality 5) You don't lke shared pointers and use raw pointers instead
I really am curious about this. I haven't put any limitation on your library or made any presumption on who your library is for, on purpose. Thanks for anyone answering !
Depends on the target. If I can rely on C++11 features being available in the project then I use std::shared_ptr. Otherwise I use boost::shared_ptr. Both times unconditionally, i.e. no auto-detection stuff.
I should also say that I find myself often using boost::intrusive_ptr instead of either std::shared_ptr or boost::shared_ptr but I'm not sure that's the answer you're looking for.
It is not the answer I am looking for, but I can easily change the question as being between boost::tuple or std::tuple, or boost::function or std::function etc. You get the idea I believe. I chose boost::shared_ptr or std::shared_ptr because I assumed that using shared pointers versus raw pointers was mainstream in the C++ programming world by now, but your answer just above foiled me <g>.
On 10/13/2016 5:14 AM, Andrey Semashev wrote:
On 10/13/16 01:58, Edward Diener wrote:
I would like to ask a design question for any Boost developers or anyone on this mailing list who might care to answer.
You are designing or working on a library, perhaps for Boost, perhaps for fun, and part of the design of the library has some public functionality taking a shared pointer as input. You:
1) Use boost::shared_ptr 2) Use std::shared_ptr 3) Use both boost::shared_ptr and std::shared_ptr with the same functionality 4) Use neither, you roll your own shared pointer-like functionality 5) You don't lke shared pointers and use raw pointers instead
I really am curious about this. I haven't put any limitation on your library or made any presumption on who your library is for, on purpose. Thanks for anyone answering !
Depends on the target. If I can rely on C++11 features being available in the project then I use std::shared_ptr. Otherwise I use boost::shared_ptr. Both times unconditionally, i.e. no auto-detection stuff.
What would you do if the target is determined the general end-user, who may be compiling your library with whatever options he chooses with whatever compiler he chooses in whatever OS he chooses ?
On 10/13/16 16:38, Edward Diener wrote:
On 10/13/2016 5:14 AM, Andrey Semashev wrote:
On 10/13/16 01:58, Edward Diener wrote:
I would like to ask a design question for any Boost developers or anyone on this mailing list who might care to answer.
You are designing or working on a library, perhaps for Boost, perhaps for fun, and part of the design of the library has some public functionality taking a shared pointer as input. You:
1) Use boost::shared_ptr 2) Use std::shared_ptr 3) Use both boost::shared_ptr and std::shared_ptr with the same functionality 4) Use neither, you roll your own shared pointer-like functionality 5) You don't lke shared pointers and use raw pointers instead
I really am curious about this. I haven't put any limitation on your library or made any presumption on who your library is for, on purpose. Thanks for anyone answering !
Depends on the target. If I can rely on C++11 features being available in the project then I use std::shared_ptr. Otherwise I use boost::shared_ptr. Both times unconditionally, i.e. no auto-detection stuff.
What would you do if the target is determined the general end-user, who may be compiling your library with whatever options he chooses with whatever compiler he chooses in whatever OS he chooses ?
There is always a list of supported targets. If that list includes a target without C++11 then I'll probably use boost::shared_ptr. That is what I'm doing in Boost.Log, which supports C++03. The choice is specific to a particular component, though. For instance, I tend to use Boost.Atomic even on C++11-enabled targets because I know it's potentially more efficient. I'm also reluctant to use std::condition_variable because I know some implementations have buggy timed functions.
On 10/13/2016 10:00 AM, Andrey Semashev wrote:
On 10/13/16 16:38, Edward Diener wrote:
On 10/13/2016 5:14 AM, Andrey Semashev wrote:
On 10/13/16 01:58, Edward Diener wrote:
I would like to ask a design question for any Boost developers or anyone on this mailing list who might care to answer.
You are designing or working on a library, perhaps for Boost, perhaps for fun, and part of the design of the library has some public functionality taking a shared pointer as input. You:
1) Use boost::shared_ptr 2) Use std::shared_ptr 3) Use both boost::shared_ptr and std::shared_ptr with the same functionality 4) Use neither, you roll your own shared pointer-like functionality 5) You don't lke shared pointers and use raw pointers instead
I really am curious about this. I haven't put any limitation on your library or made any presumption on who your library is for, on purpose. Thanks for anyone answering !
Depends on the target. If I can rely on C++11 features being available in the project then I use std::shared_ptr. Otherwise I use boost::shared_ptr. Both times unconditionally, i.e. no auto-detection stuff.
What would you do if the target is determined the general end-user, who may be compiling your library with whatever options he chooses with whatever compiler he chooses in whatever OS he chooses ?
There is always a list of supported targets. If that list includes a target without C++11 then I'll probably use boost::shared_ptr. That is what I'm doing in Boost.Log, which supports C++03.
I understand that and I think that is the general consensus. But what might happen, not that it seems to bother anyone much but me <g>, is that your library, which supports C++03, is nevertheless "compiled" by some programmer(s) using C++11 in their own project. Then their normal use of std::shared_ptr ( because it's there and naturally supported by their compiler implementation in C++11 mode ) doesn't really "play well" with your own use of boost::shared_ptr. Of course you may well say "what's the big deal, when you interface with my library you will use boost::shared_ptr and have a dependency on it, while otherwise you have chosen to use std::shared_ptr and have a dependency on your compiler's implementation. I see no problem with that." And technically you would be right, but practically the user of your library might feel differently about it.
The choice is specific to a particular component, though. For instance, I tend to use Boost.Atomic even on C++11-enabled targets because I know it's potentially more efficient. I'm also reluctant to use std::condition_variable because I know some implementations have buggy timed functions.
Understood. One of the situations I discusses in my cxx_dual library, where a programmer provides a one-off override of his own use of a particular dual library, is based on exactly what you mention just above. I personally know for instance that the std::bind and std::ref implementations in VC++10 are broken, not that Microsoft will ever go back and fix them for a compiler that very few use anymore. My OP should have also posited that boost::shared_ptr and std::shared_ptr are presume to work equally flawlessly in my 'curiosity question".
On 10/13/16 17:33, Edward Diener wrote:
On 10/13/2016 10:00 AM, Andrey Semashev wrote:
There is always a list of supported targets. If that list includes a target without C++11 then I'll probably use boost::shared_ptr. That is what I'm doing in Boost.Log, which supports C++03.
I understand that and I think that is the general consensus. But what might happen, not that it seems to bother anyone much but me <g>, is that your library, which supports C++03, is nevertheless "compiled" by some programmer(s) using C++11 in their own project. Then their normal use of std::shared_ptr ( because it's there and naturally supported by their compiler implementation in C++11 mode ) doesn't really "play well" with your own use of boost::shared_ptr. Of course you may well say "what's the big deal, when you interface with my library you will use boost::shared_ptr and have a dependency on it, while otherwise you have chosen to use std::shared_ptr and have a dependency on your compiler's implementation. I see no problem with that." And technically you would be right, but practically the user of your library might feel differently about it.
Well, that's a nuisance for the user, no doubt. But that's the consequence of the chosen balance between my burden as the library maintainer and user's convenience. Having configurable library interface can be a headache of itself, it doesn't look like a clear cut solution.
On 10/13/2016 10:56 AM, Andrey Semashev wrote:
On 10/13/16 17:33, Edward Diener wrote:
On 10/13/2016 10:00 AM, Andrey Semashev wrote:
There is always a list of supported targets. If that list includes a target without C++11 then I'll probably use boost::shared_ptr. That is what I'm doing in Boost.Log, which supports C++03.
I understand that and I think that is the general consensus. But what might happen, not that it seems to bother anyone much but me <g>, is that your library, which supports C++03, is nevertheless "compiled" by some programmer(s) using C++11 in their own project. Then their normal use of std::shared_ptr ( because it's there and naturally supported by their compiler implementation in C++11 mode ) doesn't really "play well" with your own use of boost::shared_ptr. Of course you may well say "what's the big deal, when you interface with my library you will use boost::shared_ptr and have a dependency on it, while otherwise you have chosen to use std::shared_ptr and have a dependency on your compiler's implementation. I see no problem with that." And technically you would be right, but practically the user of your library might feel differently about it.
Well, that's a nuisance for the user, no doubt. But that's the consequence of the chosen balance between my burden as the library maintainer and user's convenience. Having configurable library interface can be a headache of itself, it doesn't look like a clear cut solution.
It is certainly easier just to make a choice and stay with it. I don't think that cxx_dual is a "headache" but of course I am biased, being the author. But it is good to know where you stand on this. Thanks !
On 13 October 2016 15:33, Edward Diener wrote:
I understand that and I think that is the general consensus. But what might happen, not that it seems to bother anyone much but me <g>, is that your library, which supports C++03, is nevertheless "compiled" by some programmer(s) using C++11 in their own project. Then their normal use of std::shared_ptr ( because it's there and naturally supported by their compiler implementation in C++11 mode ) doesn't really "play well" with your own use of boost::shared_ptr. Of course you may well say "what's the big deal, when you interface with my library you will use boost::shared_ptr and have a dependency on it, while otherwise you have chosen to use std::shared_ptr and have a dependency on your compiler's implementation. I see no problem with that." And technically you would be right, but practically the user of your library might feel differently about it.
I think you've summarised nicely how I feel about it - our need to support C++03 users while not making C++11 users uncomfortable.
We do it using-declarations in namespace bst (I pronounce it 'best'!), in headers called "bst/xxx.hpp", which default to symbols from std, but can be instructed to use Boost. No auto-detection.
There's the ABI issue that Gavin Lambert mentioned earlier. Otherwise seems to work well for us.
Sometimes (like bst::placeholders), there's a tiny bit of extra work to put the Boost names in the right places, but not often.
We also sometimes switch a bunch of symbols together where that makes sense (e.g. having consistent std or boost function/thread/chrono).
I agree with Peter Dimov that "bst" or "cxx_dual" would seem to live best outside of the main Boost distrib though.
#ifndef BST_XXX_HPP
#define BST_XXX_HPP
#ifndef BST_XXX_BOOST
#include <xxx>
namespace bst
{
using std::xxx1;
using std::xxx2;
}
#else
namespace bst
#include
On 10/13/2016 11:17 AM, Sylvester-Bradley, Gareth wrote:
On 13 October 2016 15:33, Edward Diener wrote:
I understand that and I think that is the general consensus. But what might happen, not that it seems to bother anyone much but me <g>, is that your library, which supports C++03, is nevertheless "compiled" by some programmer(s) using C++11 in their own project. Then their normal use of std::shared_ptr ( because it's there and naturally supported by their compiler implementation in C++11 mode ) doesn't really "play well" with your own use of boost::shared_ptr. Of course you may well say "what's the big deal, when you interface with my library you will use boost::shared_ptr and have a dependency on it, while otherwise you have chosen to use std::shared_ptr and have a dependency on your compiler's implementation. I see no problem with that." And technically you would be right, but practically the user of your library might feel differently about it.
I think you've summarised nicely how I feel about it - our need to support C++03 users while not making C++11 users uncomfortable.
We do it using-declarations in namespace bst (I pronounce it 'best'!), in headers called "bst/xxx.hpp", which default to symbols from std, but can be instructed to use Boost. No auto-detection. There's the ABI issue that Gavin Lambert mentioned earlier. Otherwise seems to work well for us. Sometimes (like bst::placeholders), there's a tiny bit of extra work to put the Boost names in the right places, but not often. We also sometimes switch a bunch of symbols together where that makes sense (e.g. having consistent std or boost function/thread/chrono). I agree with Peter Dimov that "bst" or "cxx_dual" would seem to live best outside of the main Boost distrib though.
It seems a bit onerous for you to do what's below for each Boost versus C++ standard library you want to work with. I also don't see below how you decide to define BST_XXX_BOOST or not for some XXX library, though I assume you have some mechanism, whether automatic or manual, that makes that decision. As far as cxx_dual it really only depends on Boost Config for its automated decision-making ability. I am not keen on duplicating the Boost Config functionality which cxx_dual uses, although I will look into whether or not it could be done easily enough. I tend to doubt it. The cxx_dual support macros for naming a non header-only library and testing for valid variants for a library do use Boost PP and Boost VMD. And of course the tests use other Boost libraries extensively, including of course lightweight test. Peter's objection to cxx_dual is well-founded, but I can't help thinking that the issue is not so much the Boost monolithic distribution actually existing on disk, but that using a Boost library creates at the very minimum header file dependencies at compile time and at the maximum dependencies on shared or static libs at run-time.
#ifndef BST_XXX_HPP #define BST_XXX_HPP #ifndef BST_XXX_BOOST #include <xxx> namespace bst { using std::xxx1; using std::xxx2; } #else namespace bst #include
#include namespace bst { using boost::xxx1; using boost::xxx2; } #endif #endif Cheers, Gareth
On 13 October 2016 17:18, Edward Diener wrote:
On 10/13/2016 11:17 AM, Sylvester-Bradley, Gareth wrote: <snip>
We do it using-declarations in namespace bst (I pronounce it 'best'!), in headers called "bst/xxx.hpp", which default to symbols from std, but can be instructed to use Boost. No auto-detection. There's the ABI issue that Gavin Lambert mentioned earlier. Otherwise seems to work well for us. Sometimes (like bst::placeholders), there's a tiny bit of extra work to put the Boost names in the right places, but not often. We also sometimes switch a bunch of symbols together where that makes sense (e.g. having consistent std or boost function/thread/chrono). I agree with Peter Dimov that "bst" or "cxx_dual" would seem to live best outside of the main Boost distrib though.
It seems a bit onerous for you to do what's below for each Boost versus C++ standard library you want to work with.
The namespace alias approach is simpler, obviously. But the advantage of using-declarations is we only bring in names we know are a good match, so you can't get suckered into taking advantage of something that wouldn't be available/equivalent in bst/cxxd namespace if you were building in the other mode. And like cxx_dual, we write it once and forget about it... The using-decl approach also has the advantage that we can solve problems like the placeholders. Not sure how many of these kind of things exist but it's certainly one issue. Your test has "using namespace cxxd_bind_ns::placeholders;" (https://github.com/eldiener/cxx_dual/blob/master/test/test_bind.cpp#L38). If you omitted this, and changed the uses of _1, _2, to cxxd_bind_ns::placeholders::_1, cxxd_bind_ns::placeholders::_2, I think you'd discover you've not mapped the Boost placeholders.
I also don't see below how you decide to define BST_XXX_BOOST or not for some XXX library, though I assume you have some mechanism, whether automatic or manual, that makes that decision.
No auto-detection. Default to std, manual decision to define BST_XXX_BOOST per-project/platform.
As far as cxx_dual it really only depends on Boost Config for its automated decision-making ability. I am not keen on duplicating the Boost Config functionality which cxx_dual uses, although I will look into whether or not it could be done easily enough. I tend to doubt it.
Agreed.
The cxx_dual support macros for naming a non header-only library and testing for valid variants for a library do use Boost PP and Boost VMD. And of course the tests use other Boost libraries extensively, including of course lightweight test.
(I also have a set of BST_TEST_XXX macros that map to Boost.Test or Google Test or Catch... but that's another e-mail thread!)
Peter's objection to cxx_dual is well-founded, but I can't help thinking that the issue is not so much the Boost monolithic distribution actually existing on disk, but that using a Boost library creates at the very minimum header file dependencies at compile time and at the maximum dependencies on shared or static libs at run-time.
Basically agreed, but for C++11 users of our library, who only want to use bst/cxxd in std-mode, why should they have to have a Boost install at all? <snip> Cheers, Gareth
On 10/13/2016 12:50 PM, Sylvester-Bradley, Gareth wrote:
On 13 October 2016 17:18, Edward Diener wrote:
On 10/13/2016 11:17 AM, Sylvester-Bradley, Gareth wrote: <snip>
We do it using-declarations in namespace bst (I pronounce it 'best'!), in headers called "bst/xxx.hpp", which default to symbols from std, but can be instructed to use Boost. No auto-detection. There's the ABI issue that Gavin Lambert mentioned earlier. Otherwise seems to work well for us. Sometimes (like bst::placeholders), there's a tiny bit of extra work to put the Boost names in the right places, but not often. We also sometimes switch a bunch of symbols together where that makes sense (e.g. having consistent std or boost function/thread/chrono). I agree with Peter Dimov that "bst" or "cxx_dual" would seem to live best outside of the main Boost distrib though.
It seems a bit onerous for you to do what's below for each Boost versus C++ standard library you want to work with.
The namespace alias approach is simpler, obviously. But the advantage of using-declarations is we only bring in names we know are a good match, so you can't get suckered into taking advantage of something that wouldn't be available/equivalent in bst/cxxd namespace if you were building in the other mode. And like cxx_dual, we write it once and forget about it...
OK. But I don't know think that "suckered into taking advantage of something that wouldn't be available/equivalent" is much of a problem. Of course there may be differences between a Boost library and its C++ standard equivalent, but a programmer needs to understand what he is doing anyway when he programs a library and if he doesn't he shouldn't be tempted to use functionality which he does not understand completely. In cxx_dual you can also use using-declarations, rather than the automatic namespace alias, by using the low-level mod implementation header, but admittedly I do not explain how to do this and I appreciate that you have brought this up. I will add it to my documentation for cxx_dual.
The using-decl approach also has the advantage that we can solve problems like the placeholders. Not sure how many of these kind of things exist but it's certainly one issue. Your test has "using namespace cxxd_bind_ns::placeholders;" (https://github.com/eldiener/cxx_dual/blob/master/test/test_bind.cpp#L38). If you omitted this, and changed the uses of _1, _2, to cxxd_bind_ns::placeholders::_1, cxxd_bind_ns::placeholders::_2, I think you'd discover you've not mapped the Boost placeholders.
I agree that I did not map the placeholders for bind. I thought mapping the namespace was good enough. In general I fought against more than one namespace alias per mod in cxx_dual ( and correspondingly against more than one namespace macro per mod at the low-level ).
I also don't see below how you decide to define BST_XXX_BOOST or not for some XXX library, though I assume you have some mechanism, whether automatic or manual, that makes that decision.
No auto-detection. Default to std, manual decision to define BST_XXX_BOOST per-project/platform.
Doing it manually is fine but I think automatic should always be there for ease of use. Cxx_dual does automatic detection but then allows manual override macros to change it.
As far as cxx_dual it really only depends on Boost Config for its automated decision-making ability. I am not keen on duplicating the Boost Config functionality which cxx_dual uses, although I will look into whether or not it could be done easily enough. I tend to doubt it.
Agreed.
The cxx_dual support macros for naming a non header-only library and testing for valid variants for a library do use Boost PP and Boost VMD. And of course the tests use other Boost libraries extensively, including of course lightweight test.
(I also have a set of BST_TEST_XXX macros that map to Boost.Test or Google Test or Catch... but that's another e-mail thread!)
And I was raked over the coals for using macros <g> ! I am glad others are, like me, not afraid to use them.
Peter's objection to cxx_dual is well-founded, but I can't help thinking that the issue is not so much the Boost monolithic distribution actually existing on disk, but that using a Boost library creates at the very minimum header file dependencies at compile time and at the maximum dependencies on shared or static libs at run-time.
Basically agreed, but for C++11 users of our library, who only want to use bst/cxxd in std-mode, why should they have to have a Boost install at all?
Point taken. I am considering a stand-alone cxx_dual, but its reliance on Boost Config is a pretty big burden to overcome unless I incorporate much Boost Config logic in my own code, which I am not sanguine about doing. Boost Config is a magnificent achievement, without which cxx_dual does not exist. I acknowkledge that in the doc.
<snip>
Cheers, Gareth
On 14/10/2016 06:46, Edward Diener wrote:
Point taken. I am considering a stand-alone cxx_dual, but its reliance on Boost Config is a pretty big burden to overcome unless I incorporate much Boost Config logic in my own code, which I am not sanguine about doing. Boost Config is a magnificent achievement, without which cxx_dual does not exist. I acknowkledge that in the doc.
Perhaps it's another argument for truly-modular Boost, where you can download individual libraries rather than a monolithic release. I never really have any issues with including Boost code in desktop build environments, but it becomes a harder sell when writing embedded or cross-compiled code. (I usually still do it anyway, typically to plug holes in the libc, but it requires more justification.)
On 10/13/2016 5:45 PM, Gavin Lambert wrote:
On 14/10/2016 06:46, Edward Diener wrote:
Point taken. I am considering a stand-alone cxx_dual, but its reliance on Boost Config is a pretty big burden to overcome unless I incorporate much Boost Config logic in my own code, which I am not sanguine about doing. Boost Config is a magnificent achievement, without which cxx_dual does not exist. I acknowkledge that in the doc.
Perhaps it's another argument for truly-modular Boost, where you can download individual libraries rather than a monolithic release.
There are many other arguments for what you suggest, not just cxx-dual. But without a versioning infrastructure, where each library has not only its own versioning information but can check if it is compatible with the versioning information of all its dependencies, I doubt it will succeed. Just randomly assuming that because Boost libary X depends on Boost library Y and the end-user places some release of Boost library X somewhere and some release of Boost library Y in the same "somewhere" directory structure where library X can find it, does not mean that Boost library X will work with Boost library Y.
I never really have any issues with including Boost code in desktop build environments, but it becomes a harder sell when writing embedded or cross-compiled code. (I usually still do it anyway, typically to plug holes in the libc, but it requires more justification.)
I have actually worked as a consultant for companies in programming groups, working on desktop applications and libraries, where the use of Boost was not considered, even for just header-only libraries, because the monolithic nature of the Boost distribution was not acceptable to the company. Many of these companies would rather spend literally millions of dollars rolling their own solutions, for which Boost already provided libraries that worked much better than anything that they could do. This is just dumb but this is how many companies for which I have worked as a consultant actually think. I don't think that the solution for cxx_dual, that it should not be part of a Boost distribution to be considered usable, is any more or less true of any other Boost library. But like you say if there were a workable modular Boost-like distribution of libraries cxx_dual would benefit from it like lots of other Boost libraries also would. While I understand Peter's point I do not think that it should mitigate against the ease of use of dual libraries in cxx_dual if that is what anybody really wants to do. However from asking my question and receiving your answer and others I can see that the problem which I have solved for myself in cxx_dual is not a problem at all for the large majority of library developers who have answered my OP.
On 10/13/2016 12:50 PM, Sylvester-Bradley, Gareth wrote:
On 13 October 2016 17:18, Edward Diener wrote:
On 10/13/2016 11:17 AM, Sylvester-Bradley, Gareth wrote: <snip>
We do it using-declarations in namespace bst (I pronounce it 'best'!), in headers called "bst/xxx.hpp", which default to symbols from std, but can be instructed to use Boost. No auto-detection. There's the ABI issue that Gavin Lambert mentioned earlier. Otherwise seems to work well for us. Sometimes (like bst::placeholders), there's a tiny bit of extra work to put the Boost names in the right places, but not often. We also sometimes switch a bunch of symbols together where that makes sense (e.g. having consistent std or boost function/thread/chrono). I agree with Peter Dimov that "bst" or "cxx_dual" would seem to live best outside of the main Boost distrib though.
It seems a bit onerous for you to do what's below for each Boost versus C++ standard library you want to work with.
The namespace alias approach is simpler, obviously. But the advantage of using-declarations is we only bring in names we know are a good match, so you can't get suckered into taking advantage of something that wouldn't be available/equivalent in bst/cxxd namespace if you were building in the other mode. And like cxx_dual, we write it once and forget about it...
The using-decl approach also has the advantage that we can solve problems like the placeholders. Not sure how many of these kind of things exist but it's certainly one issue.
I have updated the documentation for CXXD to explain how you could use using-declarations with a mod's low-level implementation header to provide yourself with the greatest amount of flexibility. You can view this at http://eldiener.github.io/cxx_dual/doc/html/cxxd/sadvanced.html#cxxd.sadvanc....
Your test has "using namespace cxxd_bind_ns::placeholders;" (https://github.com/eldiener/cxx_dual/blob/master/test/test_bind.cpp#L38). If you omitted this, and changed the uses of _1, _2, to cxxd_bind_ns::placeholders::_1, cxxd_bind_ns::placeholders::_2, I think you'd discover you've not mapped the Boost placeholders.
As I originally replied I did not map the placeholders nested namespace for the bind dual library. But you are wrong in your assumption above. CXXD works perfectly well with the cxxd_bind_ns::placeholders::_n notation. There is no problem in C++ using a nested namespace for a namespace alias that is set to the namespace in which the nested namespace resides.
I also don't see below how you decide to define BST_XXX_BOOST or not for some XXX library, though I assume you have some mechanism, whether automatic or manual, that makes that decision.
No auto-detection. Default to std, manual decision to define BST_XXX_BOOST per-project/platform.
As far as cxx_dual it really only depends on Boost Config for its automated decision-making ability. I am not keen on duplicating the Boost Config functionality which cxx_dual uses, although I will look into whether or not it could be done easily enough. I tend to doubt it.
Agreed.
The cxx_dual support macros for naming a non header-only library and testing for valid variants for a library do use Boost PP and Boost VMD. And of course the tests use other Boost libraries extensively, including of course lightweight test.
(I also have a set of BST_TEST_XXX macros that map to Boost.Test or Google Test or Catch... but that's another e-mail thread!)
Peter's objection to cxx_dual is well-founded, but I can't help thinking that the issue is not so much the Boost monolithic distribution actually existing on disk, but that using a Boost library creates at the very minimum header file dependencies at compile time and at the maximum dependencies on shared or static libs at run-time.
Basically agreed, but for C++11 users of our library, who only want to use bst/cxxd in std-mode, why should they have to have a Boost install at all?
As I originally replied if you know exactly for what compiler implementation and in what C++ mode your code is going to be used you certainly can hard-code the choice of whether you are going to be using the Boost version or the C++ standard version of a particular library. And naturally if you know you will always be using C++11 you don't need the Boost version of a library if the C++ standard version is fully adequate for what you want. What I gathered from my original OP from everyone's response is that either: 1) Programmers would rather hard-code a choice of using a Boost library or its C++ standard library equivalent in their code based on whether their code was meant to be used for C++11 or above or not or 2) Roll their own hand-made system for choosing based on their individual needs rather than use a library like cxx_dual which automatically makes the choice of whether to use a Boost library or its C++ standard equivalent based on what is available at compile time. I do appreciate very much everyone who answered my query.
On 30/10/2016 07:34, Edward Diener wrote:
What I gathered from my original OP from everyone's response is that either:
1) Programmers would rather hard-code a choice of using a Boost library or its C++ standard library equivalent in their code based on whether their code was meant to be used for C++11 or above or not
or
2) Roll their own hand-made system for choosing based on their individual needs
rather than use a library like cxx_dual which automatically makes the choice of whether to use a Boost library or its C++ standard equivalent based on what is available at compile time.
FWIW, I think that's mostly due to unfamiliarity with the library, and not an indication that more people wouldn't have used it had they been aware of it. Although as the std and Boost implementations are not identical in many respects, having code switch from one to another based on environment might make people nervous, unless they feel "in control" of the switching mechanism and can adjust its choices.
On 10/30/2016 7:44 PM, Gavin Lambert wrote:
On 30/10/2016 07:34, Edward Diener wrote:
What I gathered from my original OP from everyone's response is that either:
1) Programmers would rather hard-code a choice of using a Boost library or its C++ standard library equivalent in their code based on whether their code was meant to be used for C++11 or above or not
or
2) Roll their own hand-made system for choosing based on their individual needs
rather than use a library like cxx_dual which automatically makes the choice of whether to use a Boost library or its C++ standard equivalent based on what is available at compile time.
FWIW, I think that's mostly due to unfamiliarity with the library, and not an indication that more people wouldn't have used it had they been aware of it.
I have announced the availability of cxx_dual for all 3 releases of it. I did get the impression on the first announcement that some programmers had looked at it, but I have rarely received the impression that anyone has actually tried it. I say that because there has been very little discussion about the technical areas of the library.
Although as the std and Boost implementations are not identical in many respects, having code switch from one to another based on environment might make people nervous, unless they feel "in control" of the switching mechanism and can adjust its choices.
The documentation explains how to control the algorithm which chooses between the Boost or C++ standard for any dual library or for all dual libraries. This occurs in the section entitled " Overriding the default choosing algorithm" online at http://eldiener.github.io/cxx_dual/doc/html/cxxd/sadvanced/overriding_the_de....
Hi Edward, On 29 October 2016 19:35, Edward Diener wrote:
On 10/13/2016 12:50 PM, Sylvester-Bradley, Gareth wrote:
Your test has "using namespace cxxd_bind_ns::placeholders;" (https://github.com/eldiener/cxx_dual/blob/master/test/test_bind.cpp#L38). If you omitted this, and changed the uses of _1, _2, to cxxd_bind_ns::placeholders::_1, cxxd_bind_ns::placeholders::_2, I think you'd discover you've not mapped the Boost placeholders.
As I originally replied I did not map the placeholders nested namespace for the bind dual library. But you are wrong in your assumption above. CXXD works perfectly well with the cxxd_bind_ns::placeholders::_n notation. There is no problem in C++ using a nested namespace for a namespace alias that is set to the namespace in which the nested namespace resides.
I knew that. But I didn't think Boost's placeholders were in boost::placeholders. They weren't as of 1.59.0, but it turns out I'd missed https://github.com/boostorg/bind/commit/db56733e4ed2125944b89e01cf36a9e451dd... So I'm sorry, I was out of date. Best regards, Gareth
On Monday, October 31, 2016, Sylvester-Bradley, Gareth < Gareth.Sylvester-Bradley@sony.com> wrote:
Hi Edward,
On 29 October 2016 19:35, Edward Diener wrote:
On 10/13/2016 12:50 PM, Sylvester-Bradley, Gareth wrote:
Your test has "using namespace cxxd_bind_ns::placeholders;" ( https://github.com/eldiener/cxx_dual/blob/master/test/test_bind.cpp#L38). If you omitted this, and changed the uses of _1, _2, to cxxd_bind_ns::placeholders::_1, cxxd_bind_ns::placeholders::_2, I think you'd discover you've not mapped the Boost placeholders.
As I originally replied I did not map the placeholders nested namespace for the bind dual library. But you are wrong in your assumption above. CXXD works perfectly well with the cxxd_bind_ns::placeholders::_n notation. There is no problem in C++ using a nested namespace for a namespace alias that is set to the namespace in which the nested namespace resides.
I knew that. But I didn't think Boost's placeholders were in boost::placeholders. They weren't as of 1.59.0, but it turns out I'd missed https://github.com/boostorg/bind/commit/db56733e4ed2125944b89e01cf36a9 e451dd36f5 So I'm sorry, I was out of date.
Best regards, Gareth
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/ mailman/listinfo.cgi/boost
Hi Edward, this interface seems to exist to ensure the lifetime of the object handed to my library, 5) is hence not the best option. I'd go with supporting both std::shared_ptr (default) and boost::shared_ptr in my library. 4) would be an interesting option for purely generic code, just modeling the interface of the shared_ptr type, but not restricting it to a concrete type seems smart. One could still have std::shared_ptr as the default for the template argument. boost::shared_ptr would be interesting as a way to support pre C++11 code. cheers, Jens Weller
Gesendet: Donnerstag, 13. Oktober 2016 um 00:58 Uhr Von: "Edward Diener"
An: boost@lists.boost.org Betreff: [boost] Curiousity question I would like to ask a design question for any Boost developers or anyone on this mailing list who might care to answer.
You are designing or working on a library, perhaps for Boost, perhaps for fun, and part of the design of the library has some public functionality taking a shared pointer as input. You:
1) Use boost::shared_ptr 2) Use std::shared_ptr 3) Use both boost::shared_ptr and std::shared_ptr with the same functionality 4) Use neither, you roll your own shared pointer-like functionality 5) You don't lke shared pointers and use raw pointers instead
I really am curious about this. I haven't put any limitation on your library or made any presumption on who your library is for, on purpose. Thanks for anyone answering !
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
On 10/13/2016 9:42 AM, Jens Weller wrote:
Hi Edward,
this interface seems to exist to ensure the lifetime of the object handed to my library, 5) is hence not the best option.
I'd go with supporting both std::shared_ptr (default) and boost::shared_ptr in my library.
That could be much extra code to write if you are going to support both in every inteface you design in which either is normally being used.
4) would be an interesting option for purely generic code, just modeling the interface of the shared_ptr type, but not restricting it to a concrete type seems smart. One could still have std::shared_ptr as the default for the template argument.
That is an interesting idea. But I don't think it scales that well, considering that shared pointers themselves are created based on the type of pointers being used.
boost::shared_ptr would be interesting as a way to support pre C++11 code.
I think that is what many people have said they do, If it is pre C++11 they will use boost::shared_ptr and if it is C++11+ they will use std::shared_ptr. It is eminently reasonable. But it could still lead to unhappiness for programmers using your library compiling your pre-C++11 library using C++11 and std::shared_ptr; or for programmers compiling your C++11 library and still using boost::shared_ptr ( maybe because of a bad or missing C++11 implementation of std::shared_ptr ).
cheers,
Jens Weller
Gesendet: Donnerstag, 13. Oktober 2016 um 00:58 Uhr Von: "Edward Diener"
An: boost@lists.boost.org Betreff: [boost] Curiousity question I would like to ask a design question for any Boost developers or anyone on this mailing list who might care to answer.
You are designing or working on a library, perhaps for Boost, perhaps for fun, and part of the design of the library has some public functionality taking a shared pointer as input. You:
1) Use boost::shared_ptr 2) Use std::shared_ptr 3) Use both boost::shared_ptr and std::shared_ptr with the same functionality 4) Use neither, you roll your own shared pointer-like functionality 5) You don't lke shared pointers and use raw pointers instead
I really am curious about this. I haven't put any limitation on your library or made any presumption on who your library is for, on purpose. Thanks for anyone answering !
Am 13.10.2016 um 00:58 schrieb Edward Diener:
You are designing or working on a library, perhaps for Boost, perhaps for fun, and part of the design of the library has some public functionality taking a shared pointer as input. You:
2) Use std::shared_ptr
For libraries that are consumed only within our company, std::shared_pointer ist the most convenient option. Our baseline compiler is vc12 with some older stuff in maintenance mode still on vc10, so std::shared_ptr is viable. Typically the pointer type is typedef'd in some way for user convenience.
4) Use neither, you roll your own shared pointer-like functionality
The last library that I designed also for use by external customers, I rolled my own 'handle' type which is completely opaque to users which see just a struct with no more than one single uintptr_t member. Under the covers it is a boost::intrusive_ptr. The idea is to prevent accidental misuse and not to force users taking a dependency on boost. The library itself is taking advantage of any boost functionality it sees fit. Hope this helps Dani
On 10/13/2016 1:36 PM, Daniela Engert wrote:
Am 13.10.2016 um 00:58 schrieb Edward Diener:
You are designing or working on a library, perhaps for Boost, perhaps for fun, and part of the design of the library has some public functionality taking a shared pointer as input. You:
2) Use std::shared_ptr
For libraries that are consumed only within our company, std::shared_pointer ist the most convenient option. Our baseline compiler is vc12 with some older stuff in maintenance mode still on vc10, so std::shared_ptr is viable. Typically the pointer type is typedef'd in some way for user convenience.
Makes perfect sense. It certainly helps when you know exactly in what environment the library you create will be used.
4) Use neither, you roll your own shared pointer-like functionality
The last library that I designed also for use by external customers, I rolled my own 'handle' type which is completely opaque to users which see just a struct with no more than one single uintptr_t member. Under the covers it is a boost::intrusive_ptr. The idea is to prevent accidental misuse and not to force users taking a dependency on boost. The library itself is taking advantage of any boost functionality it sees fit.
OK, thanks ! I assume that actual implementation code for your opaque type is in the built portion of a non header-only library.
Hope this helps Dani
Am 13.10.2016 um 20:01 schrieb Edward Diener:
On 10/13/2016 1:36 PM, Daniela Engert wrote:
Am 13.10.2016 um 00:58 schrieb Edward Diener:
4) Use neither, you roll your own shared pointer-like functionality
The last library that I designed also for use by external customers, I rolled my own 'handle' type which is completely opaque to users which see just a struct with no more than one single uintptr_t member. Under the covers it is a boost::intrusive_ptr. The idea is to prevent accidental misuse and not to force users taking a dependency on boost. The library itself is taking advantage of any boost functionality it sees fit.
OK, thanks ! I assume that actual implementation code for your opaque type is in the built portion of a non header-only library.
Exactly! These 'handles' refer to USB devices which may come and go. There's a 'weak handle' as well, which doesn't give access to a device but rather observes it's presence state and it's unique device instance name only. Users may construct handles only in the empty state, actual references to devices are handed out to client code by the library. And as long as there are any outstanding non-empty handles in client code, the DLL is kept locked in memory. Otherwise it may be unloaded from the process thereby freeing any remaining resources still lingering in the kernel's driver stack. Ciao Dani
On 10/14/2016 11:43 AM, Daniela Engert wrote:
Am 13.10.2016 um 20:01 schrieb Edward Diener:
On 10/13/2016 1:36 PM, Daniela Engert wrote:
Am 13.10.2016 um 00:58 schrieb Edward Diener:
4) Use neither, you roll your own shared pointer-like functionality
The last library that I designed also for use by external customers, I rolled my own 'handle' type which is completely opaque to users which see just a struct with no more than one single uintptr_t member. Under the covers it is a boost::intrusive_ptr. The idea is to prevent accidental misuse and not to force users taking a dependency on boost. The library itself is taking advantage of any boost functionality it sees fit.
OK, thanks ! I assume that actual implementation code for your opaque type is in the built portion of a non header-only library.
Exactly! These 'handles' refer to USB devices which may come and go. There's a 'weak handle' as well, which doesn't give access to a device but rather observes it's presence state and it's unique device instance name only. Users may construct handles only in the empty state, actual references to devices are handed out to client code by the library. And as long as there are any outstanding non-empty handles in client code, the DLL is kept locked in memory. Otherwise it may be unloaded from the process thereby freeing any remaining resources still lingering in the kernel's driver stack.
Ciao Dani
OK, thanks ! Many libraries are header-only libraries so the technique you describe would be more difficult, if not impossible, in such cases.
participants (13)
-
Andrey Semashev
-
Chris Glover
-
Damian Meden
-
Daniela Engert
-
Edward Diener
-
Gavin Lambert
-
Jens Weller
-
Niall Douglas
-
Oswin Krause
-
Peter Dimov
-
Stefan Seefeld
-
Sylvester-Bradley, Gareth
-
Vinnie Falco