If developers hate Boost, what do they use?

Started by
34 comments, last by Cornstalks 12 years, 2 months ago
As kunos said, there's nothing hard about writing [color=#0000ff]delete in object's destructor. If you're lazy then it's a good solution, but as GameDev article states: "smart pointers are only as smart as the person that is using them" (source: http://www.gamedev.net/blog/411/entry-2253348-smart-pointers-arent-always-so-smart/) and I choose not to use them at all.

In my opinion, Boost hardly provides anything useful. Possibly because I'm just noob at programming.
Advertisement

As kunos said, there's nothing hard about writing delete in object's destructor.

There is also nothing good about writing 'delete' in your object's destructor.

In particular, if you use exceptions, writing 'delete' in your destructor does absolutely nothing if an exception were to be thrown during your constructor (typically, the most likely place for an exception to be thrown).

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

It's not just about writing 'delete' somewhere; firstly there is a code mantaince issue of changing something and mistakes croping up.

Secondly if you are using shared_ptr as a replacement for delete then you are Doing It Wrong(tm) anyway; shared_ptr is for shared ownership and life time control of an object and only needs to be used when an object can be logically owned by multiple other objects and needs to go out of scope when all references to it are dropped. At which point you get into the area of thread safe reference counting of objects with shared ownership semantics which has just made life much harder and code more complex.
(They also allow you to route destruction via a specified function which can be very useful rather than having to make sure it happens by hand).

Circlar references are only a problem if you can't design software; if you are getting problems with passing shared_ptrs to everything then I think you need to go back and look at your design again because you are more than likely Doing It Wrong(tm) as it is illogical to have the lifetime of an object depend on another object which has its lifetime depend on the first object. Even using shared_ptr et al it is fine to pass around naked pointers to objects if you know your object lifetime semantics makes it safe.

In short; shared_ptr are good at what they do but they are not a catch all for all design problems (unique_ptr and others give difference usage semantics) nor do they remove the need for you, the programmer, to think about your design and object life times.

As for the 'fugly' arguement; C++ is hardly the most attractive of langauages however extended usage of things like this (more so when hidden behind typedefs) leads you to get use to it and removes that frankly dumb 'arguement'; I mean, hell, if you think shared_ptr<type> is ugly then you are going to hate the lambda syntax and avoiding that very powerful construct just because you think it looks 'fugly' makes you a fidiot :)


I see this around a lot. I have to say, I choose to embrace the idea of keep using "delete" as I did in the last 20 years just to avoid having my code polluted with all that shared_ptr<Whatever> that makes C++ seriously fugly.

I think C++ needs a new keyword/operator for that, kind of what microsoft did using the "^" for .NET managed references in C++.


Syntactic sugar hides stuff under the carpet, it doesn't reduce complexity.

shared_ptr pollution is symptom of approach to solving problems.

bool GraphTraverser::traverse(shared_ptr<Node> node);[/quote]

My first question: why is traverse modifying the graph? Traverse should be something that doesn't mutate structure of the graph. Same as for_each concurrentModificationException, the invalidation of iterators or similar.

Reason that leads me to such guess is passing shared_ptr. Shared_ptr only does one thing - it manages lifecycle of objects. It should therefore be passed only into parts of code that modify lifecycle, such as allocate or free objects.

Consider slight redesign:bool GraphTraverser::traverse(Node & node);Now it's obvious one cannot change the structure anymore, we'll just visit and possibly affect contents.

While we're at it:std::for_each(graph.begin(), graph.end(), Visitor());Beautiful. No need to think what this does, we're using STL's idioms. But what if I suddenly do need to modify such graph? Well - std::erase(....).


Distaste for certain features and libraries of C++ comes from cross-polination of, most commonly Java, and to lesser degree C# concepts. Idiomatic up-to-date C++ code is fairly shallow and straight-forward (excluding template meta programming).

One of biggest pieces of missing knowledge is effective mapping of problems to STL interfaces and use of <algorithm>, which cover a lot of ground.

Of course it doesn't help that many crucial libraries are in C (good ones are well designed to fit nicely) or even worse, some fairly nondescript mixture of various languages. I consider Qt to be absolute disaster, might as well call it #include <java.hpp>.

In particular, if you use exceptions.


nah.. exceptions are for pussies.. I just crash :asd:

@phantom
Actually I jumped on the lambda and auto bandwagon straight away. They are not as elegant as C#'s equivalents but they are not that bad.

@Antheus
As usual, great post... and you're right, your code is indeed beautiful and very "C++like". The example was just something on the top of my head, I don't even use a graph traverser anymore. I do think graphs are one of the things that shared_ptr dont do well, any solution I tried doesn't even come close to C#'s GC one as far as clarity and elegance. I don't know how to build a graph that is possible to iterate over with the std:for_each I'll have a look at that, but still, somewhere in Visitor you will have a shared_ptr<Node> passed in right?

I still think that syntactic sugar can make the difference between readable and unreadable code, shared_ptr<bla> has a VERY high noise to signal ratio.

Stefano Casillo
TWITTER: [twitter]KunosStefano[/twitter]
AssettoCorsa - netKar PRO - Kunos Simulazioni



You'll be hard pressed to get me to do anything in C++ without having boost, Qt or some other libraries as default.

Is something in these libraries interferring with my goals? Then they're out.


But the question shouldn't be whether to use boost or not. If should be whether OO-heavy ref-counted design is a good fit for problem being solved. Writing some UI and blob mangling app? It's fine. Writing HPC or real-time app? Throw it out. While you're at it, just use C.

There is no problem with libraries. They are fairly passive, boring and just tend to sit there. As for developers? Some are good, some are bad, some learn, some don't.


Some people paint a rosy picture about Boost. I tell people to "chew the meat and spit the bones." Some of the Boost libs are excellent and some not so much. I think highly of Boost.Insrusive and some of the other container libraries. The Serialization library though has a lot of weaknesses -- http://webEbenezer.net/comparison.html .


Brian
Ebenezer Enterprises
http://webEbenezer.net

The Serialization library though has a lot of weaknesses -- http://webEbenezer.net/comparison.html

I don't mean to be rude here, but in all honesty you can hardly be considered to an objective source on this topic.

It's fairly well understood that boost::serialisation is not the best performing alternative, but I remain unconvinced that it's a bad solution. In particular, it's one of the very few solutions that works well with heavily templated code bases.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Its less of a question about Boost and more along the lines of 'How do you choose what parts of the C++ language and libraries do you use'.

I've never met anyone that admitted to even using C++ iostreams, let alone liking them or using them for anything beyond stuff in an academic environment (i.e. homework).

STL and Boost pretty much require exception handling to be enabled. This is a dealbreaker for a lot of people, especially with codebases older than modern C++ codebases that are exception-safe. You are more or less forced to be 'C with Classes, type traits, and the STL/Boost templates and that don't allocate memory'.

RAII design more or less requires exception handling for anything useful, as you can't put any interesting code in the constructors without being able to unwind (i.e. two phase initialization is required). The cleanup-on-scope aspect is useful though without exception handling, since the destructors aren't supposed to throw anyway.

STL containers have poor to non-existant control over their memory management strategies. You can replace the 'allocator' for a container but it is near useless when the nodes linked list are forced to use the same allocator as the data they are pointing to, ruling out fixed size allocators for those objects etc. This is a lot of the motivation behind EASTL, having actual control, as the libraries are 'too generic'.

And memory management ties heavily into threading: We use Unreal Engine here which approaches the 'ridiulous' side of the spectrum on the amount of dynamic memory allocation it does at runtime. The best weapon to fight this (as we cannot redesign the engine) is to break up the memory management into lots of heaps and fixed size allocators, so that any given allocation is unlikely or not at all going to contend with a lock from other threads. Stack based allocators are also a big help, but are very not-C++-like.


My rule of thumb for using these libraries is if doesn't allocate memory, it is probably ok to use:

algorithms for std::sort is quite useful even without proper STL containers, and outperforms qsort by quite a lot due to being able to inline everything.
Type traits (either MS extensions, TR1, or Boost) can make your own templates quite a bit easier to write


I've also never seen the need for thread libraries, the code just isn't that interesting or difficult to write (and libraries tend to do things like making the stack size hard to set, or everyone uses the library in their own code and you end up with 22 thread pools and 400 threads etc)
http://www.gearboxsoftware.com/

[quote name='wood_brian' timestamp='1328037538' post='4908120']
The Serialization library though has a lot of weaknesses -- http://webEbenezer.net/comparison.html

I don't mean to be rude here, but in all honesty you can hardly be considered to an objective source on this topic.

It's fairly well understood that boost::serialisation is not the best performing alternative, but I remain unconvinced that it's a bad solution. In particular, it's one of the very few solutions that works well with heavily templated code bases.
[/quote]

Serialization in C++ is so painful I would say you should design the data structures to be as simple as possible, much like those that can be found in quake maps (X blocks of N kinds of binary data in simple structures that can be turned into trees etc easily at runtime).
http://www.gearboxsoftware.com/

I don't mean to be rude here, but in all honesty you can hardly be considered to an objective source on this topic.

Feel free to dispute the results if you like. To the best of my knowledge the results are accurate.


It's fairly well understood that boost::serialisation is not the best performing alternative, but I remain unconvinced that it's a bad solution.
[/quote]

I asked some time ago about whether the library would use move --
http://boost.2283326...-td2598382.html

The beta of Boost 1.49 is fresh off the presses and Boost hasn't improved in this area. This goes beyond performance to maintenance. Is there any plan to work on this in the future?



In particular, it's one of the very few solutions that works well with heavily templated code bases.
[/quote]

I won't argue with that.

This topic is closed to new replies.

Advertisement