<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Blog blog("Baptiste Wicht"); (Posts about Boost)</title><link>https://baptiste-wicht.com/</link><description></description><atom:link href="https://baptiste-wicht.com/categories/boost.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><lastBuildDate>Thu, 20 Aug 2026 05:27:29 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>eddic 1.2.4: New Boost Spirit X3 parser and minor cleanups</title><link>https://baptiste-wicht.com/posts/2016/06/eddic-124-new-boost-spirit-x3-parser-and-minor-cleanups.html</link><dc:creator>Baptiste Wicht</dc:creator><description>&lt;p&gt;After almost 2 years, the new version of eddic (the compiler of the EDDI
programming language) is out! eddic 1.2.4&lt;/p&gt;
&lt;p&gt;I haven't worked a lot on this project in the last years, I have been busy with
my Ph.D. related projects (ETL and DLL), my operating systems, cpm, ... I've
mostly worked on the parser to test the new version of Boost Spirit: X3. This
will be described on the next section, with the other changes in the later
section.&lt;/p&gt;
&lt;section id="new-boost-spirit-x3"&gt;
&lt;h2&gt;New Boost Spirit X3&lt;/h2&gt;
&lt;p&gt;Boost Spirit X3 is a completely revamped version of Boost Spirit X3. It's aimed
at performance, both at compile-time and at runtime and uses recent features of
modern C++. It's not compatible with Boost Spirit Qi, so you'll most likely
have to rewrite a lot of stuff, in the parser, in the Abstract Syntax Tree
(AST) and in the AST passes as well.&lt;/p&gt;
&lt;p&gt;For reference, I'm using the Boost 1.59 version.&lt;/p&gt;
&lt;section id="pros"&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;p&gt;Let's start with the pros.&lt;/p&gt;
&lt;p&gt;First, the runtime performance is definitely better. Parsing all my eddi test
cases and samples, &lt;em&gt;takes 42% less time than with the previous parser&lt;/em&gt;. It is
important to know that the old parser was very optimized, with moves instead of
copies and with a static lexer. You can take a look at &lt;a class="reference external" href="http://baptiste-wicht.com/posts/2013/06/improving-eddic-boost-spirit-parser-performances.html"&gt;this post&lt;/a&gt;
to see what was necessary to optimize the old Qi. I think it's a good result
since the new grammar does not use a lexer (x3 does not support it) and does
not need these optimizations. This improvement really was my objective. I'll
try to push it farther in the future.&lt;/p&gt;
&lt;p&gt;Compile-time performance is also much better. It takes 3 times less time to
compile the new parser (1 minute to around 20 seconds). Moreover, the new
parser is now in only one file, rather than being it necessary to split it all
over the place for compile-time performance. Even though it's not really
important for me, it's still good to have :)&lt;/p&gt;
&lt;p&gt;Especially due to the performance point, I've been able to remove some code,
the lexer, the generated static lexer and the special pointers optimizations of
the AST.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="cons"&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;p&gt;Unfortunately, there are some disadvantages of using the new Spirit X3.&lt;/p&gt;
&lt;p&gt;First, the AST needs to be changed. For good parsing performance, you need to
use x3::variant and x3::forward_ast. This is a major pain in the ass since
x3::variant is much less practical to use than boost::variant. Almost
everything is explicit, meaning uglier code than before, in my opinion.
Moreover, you need to work around x3::forward_ast for boost::get, whereas
boost::recursive_wrapper was working better in that matter. I've had to create
my own wrapper around boost::get in order to be able to use the new tree. In my
opinion, this is clearly a regression.&lt;/p&gt;
&lt;p&gt;Secondly, although X3 was also meant to remove the need to use some hacks in
the grammar, I ended up having more hacks than before. For instance, many AST
node have a fake field in order to make X3 happy. I've still had to use the
horrible eps hack at one place. I've had to create a few more rules in order to
fix type deduction that is working differently than before (worse for me). And
for some reasons, I had to replace some expectations from the grammar to make it
parse correctly. This is a really important regression in my opinion, since it
may make the parsing slower and will make the error message less nice.&lt;/p&gt;
&lt;p&gt;The previous error handling system allowed me to track the file from which an
AST node was parsed from. Although the new error handler is a lot nicer than
the old system, it does not have this feature, so I had to work around this by
using new annotation nodes and a new global handler. Overall, it's probably a
bit worse than before, but makes for lighter AST nodes.&lt;/p&gt;
&lt;p&gt;Finally, for some reason, I haven't been able to use the debug option of the
library (lots of compile time errors). That complicated a bit the debugging of
the parser.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="spirit-x3-or-spirit-qi"&gt;
&lt;h3&gt;Spirit X3 or Spirit Qi ?&lt;/h3&gt;
&lt;p&gt;Overall, I have to say I'm a bit disappointed by Spirit X3. Even though it's
faster at runtime and faster to compile, I was really expecting less issues
with it. What I really did not like was all the changes I had to make because
of x3::variant and x3::forward_ast. Overall, I really don't think it was worth
the trouble porting my parser to Spirit X3.&lt;/p&gt;
&lt;p&gt;If you have a new project, I would still consider using Boost Spirit X3.&lt;/p&gt;
&lt;p&gt;If you have an existing parser, I would probably not advice porting it to X3.
Unless you really have issues with parsing performances (and especially if you
have not already optimized QI parser), it's probably not worth the trouble and
all the time necessary for all the changes.&lt;/p&gt;
&lt;/section&gt;
&lt;/section&gt;
&lt;section id="other-changes"&gt;
&lt;h2&gt;Other changes&lt;/h2&gt;
&lt;p&gt;The other changes are much more minor. First of all, I've gotten rid of CMake.
This project has really made me hate CMake. I have actually gotten rid of it on
all my projects. I'm now using plain Makefiles and having a much better time
with them. I've also replaced boost Program Options with cxxopts. It's a much
more modern approach for program options parsing. Moreover, it's much more
lightweight and it's header only. Only advantages. There also have been lots of
changes to code (still not very good quality though).&lt;/p&gt;
&lt;/section&gt;
&lt;section id="future"&gt;
&lt;h2&gt;Future&lt;/h2&gt;
&lt;p&gt;eddic was my first real project in C++ and this can be seen in the code and the
organization. The quality of the code is really bad now that I read it again.
Some things are actually terrible :P It's probably normal since I was a
beginner in C++ at the time.&lt;/p&gt;
&lt;p&gt;For the future version of the compiler, I want to clean the code a lot more and
focus on the EDDI language adding new features. Moreover, I'll also get rid of
Boost Test Framework by using Catch (or doctest if it is ready).&lt;/p&gt;
&lt;p&gt;As for now, I'm not sure on which project I'm going to focus. Either I'll
continue working on the compiler or I'll start working again on my operating
system (thor-os) in which I was working on process concurrency (without too
much success :P). I'll probably post next updates on this post in the coming
months.&lt;/p&gt;
&lt;/section&gt;
&lt;section id="download"&gt;
&lt;h2&gt;Download&lt;/h2&gt;
&lt;p&gt;You can find the EDDI Compiler sources on the &lt;a class="reference external" href="https://github.com/wichtounet/eddic"&gt;Github repository&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The version is available in the &lt;em&gt;v1.2.4&lt;/em&gt; tag available in the GitHub
repository, in the releases pages or directly in the &amp;lt;em&amp;gt;master&amp;lt;/em&amp;gt; branch.&lt;/p&gt;
&lt;/section&gt;</description><category>Boost</category><category>C++</category><category>C++14</category><category>eddic</category><guid>https://baptiste-wicht.com/posts/2016/06/eddic-124-new-boost-spirit-x3-parser-and-minor-cleanups.html</guid><pubDate>Sun, 26 Jun 2016 20:35:04 GMT</pubDate></item><item><title>Improving eddic Boost Spirit parser performances</title><link>https://baptiste-wicht.com/posts/2013/06/improving-eddic-boost-spirit-parser-performances.html</link><dc:creator>Baptiste Wicht</dc:creator><description>&lt;p&gt;After the last changes on the data-flow framework, the parsing pass of the eddic compiler became the slowest one. I was sure there was some area of optimizations, so I decided to improve its performances.&lt;/p&gt;
&lt;p&gt;In this post, I will present the different techniques I applied and their results.&lt;/p&gt;
&lt;h4&gt;Static grammar&lt;/h4&gt;

&lt;p&gt;The first optimization that I tried was to make the grammar static, meaning that we can declare it static and it will be constructed only once and will be allocated on the data segment.It is indeed heavy to build the lexer especially but also the grammar. I would like to thank &lt;a title="sehe on github" href="https://github.com/sehe"&gt;sehe&lt;/a&gt; for this optimization, he found it after I posted a question on Stackoverflow.&lt;/p&gt;
&lt;p&gt;The lexer was very easy to make static (only add static keyword :) ), but the parser was a bit more complicated because it needs the lexer iterator to get the current position in the file. This problem has been resolved by saving the iterator into the qi::locals of the rules.&lt;/p&gt;
&lt;p&gt;The result of this optimization are amazing. It saved 33% of the time.&lt;/p&gt;
&lt;h4&gt;Expectation points&lt;/h4&gt;

&lt;p&gt;Expectation points have the interesting point that they disallow backtracking and so can improve performances in some cases. Moreover, they are always interesting because they make the grammar clearer and the error messages much better.&lt;/p&gt;
&lt;p&gt;I tried adding more expectation points to the grammar. Unfortunately, there weren't a lot of them to add. Moreover, it seems that there are some quite weird behavior with them because some times it is impossible to add them (causes compilation failure) and sometimes it just make the code don't work anymore the same way, though I don't understand why.&lt;/p&gt;
&lt;p&gt;Anyway, I have been able to add some to the grammar. These changes improve the performance by a bit more than 1%. It is not a lot, but it is still an improvement. Moreover, I'm quite sure that there are more expectation points that can be added to the code. I will take some time again later to try to add more and to understand them better.&lt;/p&gt;
&lt;h4&gt;Less skips&lt;/h4&gt;

&lt;p&gt;In my grammar, I've a special parser for getting the current position in the file to add "debug information" to the AST. This special parser was skipping over its content, but it has no content, since it is artificial. Removing it improved the performance by about half a percent.&lt;/p&gt;
&lt;h4&gt;Improve Position (debug information)&lt;/h4&gt;

&lt;p&gt;As said before, there is a special parser to get the current position in the file. This information is then stored into an eddic::ast::Position structure. This structure was holding the line number, the column, the file name and the contents of the line. The first two were ints and the last two were std::string. Each time, a copy of the strings were necessary.&lt;/p&gt;
&lt;p&gt;I avoided storing the std::string directly by storing only the number of the line as well as the index of the file. Then, the content of the file is stored in the global context and can be accessed if it is necessary to display the line where the error happened.&lt;/p&gt;
&lt;p&gt;This change gave an increase of 10% of the parsing performance.&lt;/p&gt;
&lt;h4&gt;Auto Rules&lt;/h4&gt;

&lt;p&gt;Rules in Boost Spirit have an overhead due to the cost of the virtual calls that are necessary. In theory, auto rules can improve the efficiency of the rules by removing the cost of virtual calls. Moreover, auto rules should also avoid code bloat when the rules are compiled. The rules can be inlined and better optimized.&lt;/p&gt;
&lt;p&gt;I transformed some rules to auto rules to improve performances. Unfortunately, I found that this did not improve the performances. Moreover, transforming some rules to auto rules made the performance worse. I still did let some of the rules as auto rules. I have to say that I was very disappointed by this result, I was really expecting more from this :(&lt;/p&gt;
&lt;h4&gt;Generated Static Lexer&lt;/h4&gt;

&lt;p&gt;The first time the lexer is used, it has to generate the Deterministic Finite Automaton (DFA) that is used to identify the different tokens. This process takes time. There is way to avoid this by using the static model of Boost Spirit Lex. With that, the code is generated with the complete DFA and then it doesn't have to be initialized again.&lt;/p&gt;
&lt;p&gt;I was not expecting a lot from this because the lexer was already static and so was initialized only once. Indeed, it resulted in less than half a percent improvement.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;Even if I've been able to largely reduce the overhead of the parsing by more than 40%, it still has a big overhead. Indeed, it still represents 36 percent of the whole process of compiling a source file. I think it is still too much.&lt;/p&gt;
&lt;p&gt;Moreover, an interesting fact is that the optimization I would have thought to be very effective (auto rules especially) did not have the expected effect, but making the grammar static, which I would not have thought of, was very effective.&lt;/p&gt;
&lt;p&gt;When profiled, the final version shows that quite some time is spent in destructing the multi_pass, which is quite odd. And it also seems that transforming the string operators to ast::Operator is not very effective, but I do not know how to improve that at this point.&lt;/p&gt;
&lt;p&gt;I won't probably work on that again for the version 1.2.4 of eddic, but I will eventually take some time again for the version 1.3.0 to improve it again.&lt;/p&gt;</description><category>Benchmarks</category><category>Boost</category><category>C++11</category><category>Compilers</category><category>EDDI</category><category>Performances</category><guid>https://baptiste-wicht.com/posts/2013/06/improving-eddic-boost-spirit-parser-performances.html</guid><pubDate>Mon, 10 Jun 2013 06:16:42 GMT</pubDate></item><item><title>C++ Benchmark - std::list VS boost::intrusive::list</title><link>https://baptiste-wicht.com/posts/2012/12/cpp-benchmark-std-list-boost-intrusive-list.html</link><dc:creator>Baptiste Wicht</dc:creator><description>&lt;p&gt;Recently, we saw that the &lt;a title="C++ benchmark – std::vector VS std::list VS std::deque" href="http://www.baptiste-wicht.com/2012/12/cpp-benchmark-vector-list-deque/"&gt;std::list performance was not really good&lt;/a&gt; when it comes to searching it or iterating through it.In this post, we will see an alternative to the std::list: the boost::intrusive::list from the Boost C++ libraries. It is not a well known library but it can be useful in some specific cases. I will focus on how this implementation performs compared to an std::list.&lt;/p&gt;
&lt;p&gt;An intrusive list does not store copies of the object but the objects itself. Because it stores the objects, it is necessary to add information to the object data structure directly to link them together, that is why it is called an intrusive list. This has a big advantage, the list does not have to allocate any memory at all to insert objects. In a std::list if you insert an object, a node object will be created containing a copy of the object, but not in an intrusive list where only the pointers to the next and to the previous element of the inserted object are updated. Another advantage is that if you have a reference to an object you can directly obtain an iterator to this object in O(1), an operation that would be in O(n) with a std::list. Iteration is faster because it needs less memory accesses.&lt;/p&gt;
&lt;p&gt;On the other hand, an intrusive list has also several drawbacks. First of all, it is intrusive. It means that you have to change the definition of the type that is stored inside the intrusive list. Then, and it be very complicated, it is up to the developer to manage the life time of the objects. It means that it is up to you to allocate and deallocate memory for each objects that you want to put in your collection. For instance, if you store an object into an intrusive list and later delete this object without removing it from the list, you will have broken you list. It is also less safe because the container can be modified from outside simply by modifying the pointers directly inside the objects.&lt;/p&gt;
&lt;p&gt;This article is not a tutorial for Boost intrusive collections, I will just focus on the performance aspect, if you want to learn how to use them, you can consult &lt;a href="http://www.boost.org/doc/libs/1_52_0/doc/html/intrusive.html" title="Boost Intrusive 1.52"&gt;the official documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A boost::intrusive::list can be configured in three mode:&lt;/p&gt;
&lt;ol&gt;
    &lt;li&gt;Normal mode: No special features&lt;/li&gt;
    &lt;li&gt;Safe mode: The hook is initialized to a default safe state and the container check this state before inserting a value. The state of a removed node is also updated correctly. It can be used to detect programming errors. It implies a small performance overhead. This is the default mode.&lt;/li&gt;
    &lt;li&gt;Auto unlink mode: When an object gets destructed it is automatically removed from the container. This mode has also the properties of the safe mode.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The mode is chosen at constant time by configuring the hook of the data type. In this article, all three mode will be tested. Here are the four types that will be tested:&lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;list : std::list&lt;/li&gt;
    &lt;li&gt;normal_ilist : boost::intrusive::list in normal mode&lt;/li&gt;
    &lt;li&gt;safe_ilist : boost::intrusive::list in safe mode&lt;/li&gt;
    &lt;li&gt;auto_unlink_ilist : boost::intrusive::list in auto unlink mode&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The data types are varying in size, they hold an array of longs and the size of the array varies to change the size of the data type. In each graph, the size of the data type is indicated. It is the size of the normal data type. The intrusive data types are always 16 bytes bigger than the normal data types.&lt;/p&gt;
&lt;p&gt;In the graphs and in the text, &lt;em&gt;n&lt;/em&gt; is used to refer to the number of elements of the collection.&lt;/p&gt;
&lt;p&gt;All the tests performed have been performed on an Intel Core i7 Q 820  @ 1.73GHz. The code has been compiled in 64 bits with GCC 4.7.2 with the given options: &lt;em&gt;-std=c++11 -O2 -fomit-frame-pointer -march=native&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;For each graph, the vertical axis represent the amount of time necessary to perform the operations, so the lower values are the better. The horizontal axis is always the number of elements of the collection. For some graph, the logarithmic scale could be clearer, a button is available after each graph to change the vertical scale to a logarithmic scale.&lt;/p&gt;
&lt;p&gt;So let's see these data structures in practice.&lt;/p&gt;
&lt;!--nextpage--&gt;

&lt;h3&gt;Fill list&lt;/h3&gt;

&lt;p&gt;The first test that is performed is how long does it take to fill each data structure. For the std::list, each value is entered directly. For the intrusive list variations, the data are entered into a vector and then pushed back to the intrusive list.&lt;/p&gt;
&lt;p&gt;So, let's test them:&lt;/p&gt;
&lt;div id="graph_0" style="width: 600px; height: 400px;"&gt;&lt;/div&gt;
&lt;p&gt;&lt;input id="button_graph_0" type="button" value="Logarithmic scale"&gt;
&lt;script type="text/javascript"&gt;function draw_graph_0(){var graph=new google.visualization.LineChart(document.getElementById('graph_0'));var data=google.visualization.arrayToDataTable([['x','auto_unlink_list','safe_list','normal_ilist','list'],['100000',265,261,491,2926],['200000',534,498,773,4717],['300000',1874,1841,1901,7201],['400000',2670,2657,2749,9696],['500000',3410,3447,3486,11608],['600000',4044,4095,4050,14024],['700000',4653,4549,4626,16750],['800000',5406,5320,5414,18568],['900000',5995,5926,6160,20880],['1000000',6806,6785,6784,22795],]);var options={curveType:"function",animation:{duration:1200,easing:"in"},title:"fill_back - Normal&lt;8u&gt;",width:'600px',height:'400px',hAxis:{title:"Number of elements",slantedText:true},vAxis:{title:"us",viewWindow:{min:0}}};graph.draw(data,options);var button=document.getElementById('button_graph_0');button.onclick=function(){if(options.vAxis.logScale){button.value="Logarithmic Scale";}else{button.value="Normal scale";}options.vAxis.logScale=!options.vAxis.logScale;graph.draw(data,options);};}&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;We can see that filling a list is about thrice slower than an intrusive version. This is quite logical because there are much less memory allocations in the case of the intrusive lists. The differences between the different intrusive versions are not very big. The normal version is the fastest, then the auto unlink and finally the safe version is the slowest.&lt;/p&gt;
&lt;p&gt;If we increase the size of the data type a bit:&lt;/p&gt;
&lt;div id="graph_1" style="width: 600px; height: 400px;"&gt;&lt;/div&gt;
&lt;p&gt;&lt;input id="button_graph_1" type="button" value="Logarithmic scale"&gt;
&lt;script type="text/javascript"&gt;function draw_graph_1(){var graph=new google.visualization.LineChart(document.getElementById('graph_1'));var data=google.visualization.arrayToDataTable([['x','auto_unlink_list','safe_list','normal_ilist','list'],['100000',850,894,967,2685],['200000',1760,1671,1747,5742],['300000',3987,3916,3970,8517],['400000',5257,5191,5238,10919],['500000',6561,6813,6661,13614],['600000',7943,8197,7954,15874],['700000',9251,9523,9049,18625],['800000',10463,10865,10417,21114],['900000',11736,11992,11734,23824],['1000000',13137,13423,13055,26555],]);var options={curveType:"function",animation:{duration:1200,easing:"in"},title:"fill_back - Normal&lt;32u&gt;",width:'600px',height:'400px',hAxis:{title:"Number of elements",slantedText:true},vAxis:{title:"us",viewWindow:{min:0}}};graph.draw(data,options);var button=document.getElementById('button_graph_1');button.onclick=function(){if(options.vAxis.logScale){button.value="Logarithmic Scale";}else{button.value="Normal scale";}options.vAxis.logScale=!options.vAxis.logScale;graph.draw(data,options);};}&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;The results remains more or less the same, but this time there is less difference between list and intrusive list.&lt;/p&gt;
&lt;div id="graph_2" style="width: 600px; height: 400px;"&gt;&lt;/div&gt;
&lt;p&gt;&lt;input id="button_graph_2" type="button" value="Logarithmic scale"&gt;
&lt;script type="text/javascript"&gt;function draw_graph_2(){var graph=new google.visualization.LineChart(document.getElementById('graph_2'));var data=google.visualization.arrayToDataTable([['x','auto_unlink_list','safe_list','normal_ilist','list'],['100000',2131,2109,2923,39337],['200000',3834,3830,5792,90984],['300000',6454,6508,8604,138087],['400000',8499,8926,11614,185607],['500000',11068,10874,14455,230798],['600000',13009,13052,17307,275473],['700000',14965,15008,20593,326638],['800000',17082,17186,23109,372022],['900000',19283,19476,26182,415426],['1000000',21503,21569,29463,463462],]);var options={curveType:"function",animation:{duration:1200,easing:"in"},title:"fill_back - Normal&lt;1024u&gt;",width:'600px',height:'400px',hAxis:{title:"Number of elements",slantedText:true},vAxis:{title:"us",viewWindow:{min:0}}};graph.draw(data,options);var button=document.getElementById('button_graph_2');button.onclick=function(){if(options.vAxis.logScale){button.value="Logarithmic Scale";}else{button.value="Normal scale";}options.vAxis.logScale=!options.vAxis.logScale;graph.draw(data,options);};}&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;This time, the results are really different. The intrusive versions are twenty times faster than a standard list. This comes from dynamic allocations of large blocks that is very expensive. In the case of intrusive list, there are no memory allocations, just modifications of pointers, so it it is normal that for big blocks the difference is higher.&lt;/p&gt;
&lt;p&gt;We can see that for push_back operations, the intrusive are clearly faster. For small data types, they can be up to three times faster. The difference can be much higher with very big data types. There are no big differences between the different versions of the intrusive lists. The normal mode is about 10% faster than the safe mode.&lt;/p&gt;
&lt;!--nextpage--&gt;

&lt;h3&gt;Destruction of list&lt;/h3&gt;

&lt;p&gt;The second test is about the time necessary to destruct a collection. For a list, the list is simply allocated on the heap and destructed with delete operator. For an intrusive list, both the vector and the list are allocated on the heap. The time is computed to delete both the vector and the intrusive list.&lt;/p&gt;
&lt;p&gt;Let's take a look at the results:&lt;/p&gt;
&lt;div id="graph_3" style="width: 600px; height: 400px;"&gt;&lt;/div&gt;
&lt;p&gt;&lt;input id="button_graph_3" type="button" value="Logarithmic scale"&gt;
&lt;script type="text/javascript"&gt;function draw_graph_3(){var graph=new google.visualization.LineChart(document.getElementById('graph_3'));var data=google.visualization.arrayToDataTable([['x','auto_unlink_list','safe_list','normal_ilist','list'],['100000',298,283,0,2420],['200000',588,585,0,3132],['300000',1196,1217,1,4487],['400000',2180,2350,1,6478],['500000',3169,3098,1,7259],['600000',3975,3957,1,8609],['700000',4569,4798,1,10018],['800000',5189,5311,1,11501],['900000',5927,6022,1,13004],['1000000',6616,6592,1,14423],]);var options={curveType:"function",animation:{duration:1200,easing:"in"},title:"destruction - Normal&lt;8u&gt;",width:'600px',height:'400px',hAxis:{title:"Number of elements",slantedText:true},vAxis:{title:"us",viewWindow:{min:0}}};graph.draw(data,options);var button=document.getElementById('button_graph_3');button.onclick=function(){if(options.vAxis.logScale){button.value="Logarithmic Scale";}else{button.value="Normal scale";}options.vAxis.logScale=!options.vAxis.logScale;graph.draw(data,options);};}&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;The impressive result is that the normal mode is almost free. It is normal because the destructor of the objects does not do anything. Neither the list does anything about the state of the object after it has been removed. The other two intrusive versions performs the same and twice faster than a list.&lt;/p&gt;
&lt;p&gt;Let's increase a bit the size:&lt;/p&gt;
&lt;div id="graph_4" style="width: 600px; height: 400px;"&gt;&lt;/div&gt;
&lt;p&gt;&lt;input id="button_graph_4" type="button" value="Logarithmic scale"&gt;
&lt;script type="text/javascript"&gt;function draw_graph_4(){var graph=new google.visualization.LineChart(document.getElementById('graph_4'));var data=google.visualization.arrayToDataTable([['x','auto_unlink_list','safe_list','normal_ilist','list'],['100000',515,531,0,1490],['200000',1997,1964,0,3370],['300000',4022,3818,1,5585],['400000',5219,5456,1,7099],['500000',6693,6847,1,9054],['600000',7859,7984,1,11131],['700000',9456,9382,1,12248],['800000',10637,10493,1,14059],['900000',12433,11882,1,15933],['1000000',13646,13098,1,17434],]);var options={curveType:"function",animation:{duration:1200,easing:"in"},title:"destruction - Normal&lt;32u&gt;",width:'600px',height:'400px',hAxis:{title:"Number of elements",slantedText:true},vAxis:{title:"us",viewWindow:{min:0}}};graph.draw(data,options);var button=document.getElementById('button_graph_4');button.onclick=function(){if(options.vAxis.logScale){button.value="Logarithmic Scale";}else{button.value="Normal scale";}options.vAxis.logScale=!options.vAxis.logScale;graph.draw(data,options);};}&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;This time, the std::list version is getting closer to the auto unlink and safe versions. The auto unlink version is a bit slower than the safe version. The normal mode is still free.&lt;/p&gt;
&lt;p&gt;Increasing it a bit again:&lt;/p&gt;
&lt;div id="graph_5" style="width: 600px; height: 400px;"&gt;&lt;/div&gt;
&lt;p&gt;&lt;input id="button_graph_5" type="button" value="Logarithmic scale"&gt;
&lt;script type="text/javascript"&gt;function draw_graph_5(){var graph=new google.visualization.LineChart(document.getElementById('graph_5'));var data=google.visualization.arrayToDataTable([['x','auto_unlink_list','safe_list','normal_ilist','list'],['100000',4110,4158,1,4388],['200000',8357,8231,1,8949],['300000',12461,11871,1,12417],['400000',16097,16064,1,16249],['500000',19754,19990,1,19181],['600000',23724,24022,1,22019],['700000',28973,28421,2,24928],['800000',32638,32793,1,31896],['900000',37257,36320,1,35455],['1000000',40422,41037,1,39357],]);var options={curveType:"function",animation:{duration:1200,easing:"in"},title:"destruction - Normal&lt;128u&gt;",width:'600px',height:'400px',hAxis:{title:"Number of elements",slantedText:true},vAxis:{title:"us",viewWindow:{min:0}}};graph.draw(data,options);var button=document.getElementById('button_graph_5');button.onclick=function(){if(options.vAxis.logScale){button.value="Logarithmic Scale";}else{button.value="Normal scale";}options.vAxis.logScale=!options.vAxis.logScale;graph.draw(data,options);};}&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;We can see that the list is a small bit faster than the other two versions.&lt;/p&gt;
&lt;p&gt;If we push the memory to its limit:&lt;/p&gt;
&lt;div id="graph_6" style="width: 600px; height: 400px;"&gt;&lt;/div&gt;
&lt;p&gt;&lt;input id="button_graph_6" type="button" value="Logarithmic scale"&gt;
&lt;script type="text/javascript"&gt;function draw_graph_6(){var graph=new google.visualization.LineChart(document.getElementById('graph_6'));var data=google.visualization.arrayToDataTable([['x','auto_unlink_list','safe_list','normal_ilist','list'],['100000',2582,2689,1,5669],['200000',10506,10450,1,19719],['300000',16490,16429,1,33569],['400000',21521,21702,1,47179],['500000',27188,27217,1,59640],['600000',32507,32470,1,70116],['700000',37288,37344,1,81122],['800000',42825,42611,1,91972],['900000',48004,48315,1,104401],['1000000',53439,53988,1,114482],]);var options={curveType:"function",animation:{duration:1200,easing:"in"},title:"destruction - Normal&lt;1024u&gt;",width:'600px',height:'400px',hAxis:{title:"Number of elements",slantedText:true},vAxis:{title:"us",viewWindow:{min:0}}};graph.draw(data,options);var button=document.getElementById('button_graph_6');button.onclick=function(){if(options.vAxis.logScale){button.value="Logarithmic Scale";}else{button.value="Normal scale";}options.vAxis.logScale=!options.vAxis.logScale;graph.draw(data,options);};}&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;This time, the list is again slower. I'm not sure of why this happens, but it is certainly because of the memory allocator that has two allocate too many big blocks, which tends to be more costly than many small.&lt;/p&gt;
&lt;p&gt;For the destruction, the normal mode proved its high strength, being totally free to destroy. The safe and auto unlink modes are proving much more expensive during destruction, but still quite a bit faster than a standard list.&lt;/p&gt;
&lt;p&gt;It is also necessary to keep in mind that the destruction is generally not a common operation and is about 4 times faster than insertion. In practice, neither push_back nor destruction are critical in choosing a data structure.&lt;/p&gt;
&lt;!--nextpage--&gt;

&lt;h3&gt;Linear Search in a list&lt;/h3&gt;

&lt;p&gt;The next operation that will benchmark is the linear search. The container is filled with all the numbers in [0, n] and shuffled. Then, each number in [0, n] is searched in the container with std::find that performs a simple linear search.&lt;/p&gt;
&lt;p&gt;How do the different data structures perform:&lt;/p&gt;
&lt;div id="graph_7" style="width: 600px; height: 400px;"&gt;&lt;/div&gt;
&lt;p&gt;&lt;input id="button_graph_7" type="button" value="Logarithmic scale"&gt;
&lt;script type="text/javascript"&gt;function draw_graph_7(){var graph=new google.visualization.LineChart(document.getElementById('graph_7'));var data=google.visualization.arrayToDataTable([['x','auto_unlink_list','safe_list','normal_ilist','list'],['1000',1213,1211,1200,1463],['2000',5715,5561,5931,6992],['3000',12451,11619,11608,14251],['4000',19338,20142,19208,24840],['5000',30147,30889,29863,40523],['6000',42941,44530,43289,59541],['7000',59717,62534,58851,80416],['8000',77519,78889,77188,104198],['9000',99738,99434,100375,135452],['10000',123829,123216,123506,169720],]);var options={curveType:"function",animation:{duration:1200,easing:"in"},title:"linear_search - Normal&lt;8u&gt;",width:'600px',height:'400px',hAxis:{title:"Number of elements",slantedText:true},vAxis:{title:"us",viewWindow:{min:0}}};graph.draw(data,options);var button=document.getElementById('button_graph_7');button.onclick=function(){if(options.vAxis.logScale){button.value="Logarithmic Scale";}else{button.value="Normal scale";}options.vAxis.logScale=!options.vAxis.logScale;graph.draw(data,options);};}&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;As expected, the intrusive list versions are faster than the standard list. The margin is about 40%. The intrusive versions have a better locality than the standard list because there is one less indirection.&lt;/p&gt;
&lt;p&gt;Increasing the data type size:&lt;/p&gt;
&lt;div id="graph_8" style="width: 600px; height: 400px;"&gt;&lt;/div&gt;
&lt;p&gt;&lt;input id="button_graph_8" type="button" value="Logarithmic scale"&gt;
&lt;script type="text/javascript"&gt;function draw_graph_8(){var graph=new google.visualization.LineChart(document.getElementById('graph_8'));var data=google.visualization.arrayToDataTable([['x','auto_unlink_list','safe_list','normal_ilist','list'],['1000',2901,2862,2940,2757],['2000',14258,14242,14413,18990],['3000',37327,37078,37387,48716],['4000',69310,68935,69152,86224],['5000',109444,110199,108283,134128],['6000',158570,158392,158398,202273],['7000',219949,220489,219070,266387],['8000',285885,289721,283485,342109],['9000',363603,361367,362935,424984],['10000',445068,451009,447940,525289],]);var options={curveType:"function",animation:{duration:1200,easing:"in"},title:"linear_search - Normal&lt;128u&gt;",width:'600px',height:'400px',hAxis:{title:"Number of elements",slantedText:true},vAxis:{title:"us",viewWindow:{min:0}}};graph.draw(data,options);var button=document.getElementById('button_graph_8');button.onclick=function(){if(options.vAxis.logScale){button.value="Logarithmic Scale";}else{button.value="Normal scale";}options.vAxis.logScale=!options.vAxis.logScale;graph.draw(data,options);};}&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;The margin has decreased a bit to about 15%. As the data object does not fit in cache we have higher cache misses rate.&lt;/p&gt;
&lt;p&gt;If we increase it to the maximum:&lt;/p&gt;
&lt;div id="graph_9" style="width: 600px; height: 400px;"&gt;&lt;/div&gt;
&lt;p&gt;&lt;input id="button_graph_9" type="button" value="Logarithmic scale"&gt;
&lt;script type="text/javascript"&gt;function draw_graph_9(){var graph=new google.visualization.LineChart(document.getElementById('graph_9'));var data=google.visualization.arrayToDataTable([['x','auto_unlink_list','safe_list','normal_ilist','list'],['1000',3517,3818,3487,3570],['2000',19342,18999,18875,22972],['3000',59722,59728,60953,60749],['4000',116755,118256,117172,123127],['5000',194630,195522,192977,204278],['6000',287911,287099,291353,296178],['7000',395506,404527,396043,413398],['8000',519636,527051,527183,549713],['9000',662320,669371,672484,693154],['10000',831052,828032,832995,859092],]);var options={curveType:"function",animation:{duration:1200,easing:"in"},title:"linear_search - Normal&lt;1024u&gt;",width:'600px',height:'400px',hAxis:{title:"Number of elements",slantedText:true},vAxis:{title:"us",viewWindow:{min:0}}};graph.draw(data,options);var button=document.getElementById('button_graph_9');button.onclick=function(){if(options.vAxis.logScale){button.value="Logarithmic Scale";}else{button.value="Normal scale";}options.vAxis.logScale=!options.vAxis.logScale;graph.draw(data,options);};}&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;Again, the margin decreased, to 3%.&lt;/p&gt;
&lt;p&gt;For linear searching, the intrusive versions are clearly faster, however, not by a high advantage and this advantage tends to get lower with bigger data types. I would really have expected a more interesting result here. We will see with the next results if it gets better.&lt;/p&gt;
&lt;!--nextpage--&gt;

&lt;h3&gt;Iteration over a list&lt;/h3&gt;

&lt;p&gt;This time, we will test the iteration over a whole collection. The iterate is done with the C++11 foreach loop (taking a reference) and the data is used to increment a counter (to make sure the loop is not optimized away.&lt;/p&gt;
&lt;p&gt;Let's start with our small data type:&lt;/p&gt;
&lt;div id="graph_10" style="width: 600px; height: 400px;"&gt;&lt;/div&gt;
&lt;p&gt;&lt;input id="button_graph_10" type="button" value="Logarithmic scale"&gt;
&lt;script type="text/javascript"&gt;function draw_graph_10(){var graph=new google.visualization.LineChart(document.getElementById('graph_10'));var data=google.visualization.arrayToDataTable([['x','auto_unlink_list','safe_list','normal_ilist','list'],['100000',204,202,209,276],['200000',430,404,439,715],['300000',967,956,1086,1969],['400000',1837,1826,1870,2672],['500000',2705,2668,2699,3130],['600000',3176,3110,3217,3815],['700000',3856,3678,3575,4363],['800000',4209,4090,4095,4860],['900000',4778,4334,4433,5511],['1000000',4934,4908,4656,5541],]);var options={curveType:"function",animation:{duration:1200,easing:"in"},title:"iterate - Normal&lt;8u&gt;",width:'600px',height:'400px',hAxis:{title:"Number of elements",slantedText:true},vAxis:{title:"us",viewWindow:{min:0}}};graph.draw(data,options);var button=document.getElementById('button_graph_10');button.onclick=function(){if(options.vAxis.logScale){button.value="Logarithmic Scale";}else{button.value="Normal scale";}options.vAxis.logScale=!options.vAxis.logScale;graph.draw(data,options);};}&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;The standard list is indeed slower than the other versions (by about 20%). Which is expected due to their better data locality. However, the results are not very stable (probably too fast, many things can intervene). I was expecting better results.&lt;/p&gt;
&lt;p&gt;Let's go with a higher data type:&lt;/p&gt;
&lt;div id="graph_11" style="width: 600px; height: 400px;"&gt;&lt;/div&gt;
&lt;p&gt;&lt;input id="button_graph_11" type="button" value="Logarithmic scale"&gt;
&lt;script type="text/javascript"&gt;function draw_graph_11(){var graph=new google.visualization.LineChart(document.getElementById('graph_11'));var data=google.visualization.arrayToDataTable([['x','auto_unlink_list','safe_list','normal_ilist','list'],['100000',3694,3635,3467,3830],['200000',6779,6766,6430,7070],['300000',9472,9819,9291,10270],['400000',12354,12322,12165,13588],['500000',15188,15270,15079,16725],['600000',18447,18246,17797,19875],['700000',20925,20578,20596,23256],['800000',23539,23780,23421,26451],['900000',26492,26237,25975,29785],['1000000',29757,29482,28681,32752],]);var options={curveType:"function",animation:{duration:1200,easing:"in"},title:"iterate - Normal&lt;128u&gt;",width:'600px',height:'400px',hAxis:{title:"Number of elements",slantedText:true},vAxis:{title:"us",viewWindow:{min:0}}};graph.draw(data,options);var button=document.getElementById('button_graph_11');button.onclick=function(){if(options.vAxis.logScale){button.value="Logarithmic Scale";}else{button.value="Normal scale";}options.vAxis.logScale=!options.vAxis.logScale;graph.draw(data,options);};}&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;This time, the results look better, but there are less difference between the standard list and the intrusive versions. The intrusive versions are faster by about 10%.&lt;/p&gt;
&lt;p&gt;If we take a bigger data type:&lt;/p&gt;
&lt;div id="graph_12" style="width: 600px; height: 400px;"&gt;&lt;/div&gt;
&lt;p&gt;&lt;input id="button_graph_12" type="button" value="Logarithmic scale"&gt;
&lt;script type="text/javascript"&gt;function draw_graph_12(){var graph=new google.visualization.LineChart(document.getElementById('graph_12'));var data=google.visualization.arrayToDataTable([['x','auto_unlink_list','safe_list','normal_ilist','list'],['100000',2797,2649,2496,5211],['200000',10148,10227,10199,10701],['300000',15379,15544,15458,15189],['400000',20181,20599,20213,20135],['500000',25481,25517,25381,25567],['600000',30407,30408,30326,29938],['700000',35187,35343,35498,34985],['800000',40094,39874,40172,40027],['900000',44875,45329,45314,44964],['1000000',49584,50143,50405,49737],]);var options={curveType:"function",animation:{duration:1200,easing:"in"},title:"iterate - Normal&lt;1024u&gt;",width:'600px',height:'400px',hAxis:{title:"Number of elements",slantedText:true},vAxis:{title:"us",viewWindow:{min:0}}};graph.draw(data,options);var button=document.getElementById('button_graph_12');button.onclick=function(){if(options.vAxis.logScale){button.value="Logarithmic Scale";}else{button.value="Normal scale";}options.vAxis.logScale=!options.vAxis.logScale;graph.draw(data,options);};}&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;This time, there is no more difference between the different versions.&lt;/p&gt;
&lt;p&gt;Just like the results for linear search, the intrusive versions are faster but the difference is not huge. For very small data type, there is a gain of about 15 to 20 percent, but on very big data types, there is no more increase in performance. Again, I would have expected better results for the intrusive versions.&lt;/p&gt;
&lt;!--nextpage--&gt;

&lt;h3&gt;Write to elements of the list&lt;/h3&gt;

&lt;p&gt;This test is almost the same as the previous one, but this time each element of the collection is modified by incrementing one of its field.&lt;/p&gt;
&lt;p&gt;Let's see if the results are different this time.&lt;/p&gt;
&lt;div id="graph_13" style="width: 600px; height: 400px;"&gt;&lt;/div&gt;
&lt;p&gt;&lt;input id="button_graph_13" type="button" value="Logarithmic scale"&gt;
&lt;script type="text/javascript"&gt;function draw_graph_13(){var graph=new google.visualization.LineChart(document.getElementById('graph_13'));var data=google.visualization.arrayToDataTable([['x','auto_unlink_list','safe_list','normal_ilist','list'],['100000',267,290,263,343],['200000',579,583,548,889],['300000',1111,1142,1114,2151],['400000',2155,2143,2146,3197],['500000',3193,3186,3163,4168],['600000',4016,3991,3978,5179],['700000',4727,4916,4717,6026],['800000',5560,5534,5440,6977],['900000',6125,6157,6064,7693],['1000000',6830,6920,6785,8613],]);var options={curveType:"function",animation:{duration:1200,easing:"in"},title:"write - Normal&lt;8u&gt;",width:'600px',height:'400px',hAxis:{title:"Number of elements",slantedText:true},vAxis:{title:"us",viewWindow:{min:0}}};graph.draw(data,options);var button=document.getElementById('button_graph_13');button.onclick=function(){if(options.vAxis.logScale){button.value="Logarithmic Scale";}else{button.value="Normal scale";}options.vAxis.logScale=!options.vAxis.logScale;graph.draw(data,options);};}&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;The results are more stable than before. We can see that the normal mode is leading the results by a bit less than 30%. Just like for iteration, there no real difference between the different modes.&lt;/p&gt;
&lt;p&gt;Let's increase the data size by a bit:&lt;/p&gt;
&lt;div id="graph_14" style="width: 600px; height: 400px;"&gt;&lt;/div&gt;
&lt;p&gt;&lt;input id="button_graph_14" type="button" value="Logarithmic scale"&gt;
&lt;script type="text/javascript"&gt;function draw_graph_14(){var graph=new google.visualization.LineChart(document.getElementById('graph_14'));var data=google.visualization.arrayToDataTable([['x','auto_unlink_list','safe_list','normal_ilist','list'],['100000',505,513,530,1069],['200000',1957,1991,2023,3222],['300000',4056,4053,4000,4806],['400000',5572,5493,5587,6408],['500000',6763,6798,6714,8578],['600000',8224,8142,8050,10037],['700000',9520,9622,9568,12272],['800000',10982,11451,10947,13818],['900000',12195,12305,12185,15103],['1000000',14043,13657,13775,17187],]);var options={curveType:"function",animation:{duration:1200,easing:"in"},title:"write - Normal&lt;32u&gt;",width:'600px',height:'400px',hAxis:{title:"Number of elements",slantedText:true},vAxis:{title:"us",viewWindow:{min:0}}};graph.draw(data,options);var button=document.getElementById('button_graph_14');button.onclick=function(){if(options.vAxis.logScale){button.value="Logarithmic Scale";}else{button.value="Normal scale";}options.vAxis.logScale=!options.vAxis.logScale;graph.draw(data,options);};}&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;The results are the same, still 30% better for the intrusive version.&lt;/p&gt;
&lt;p&gt;Bigger data type again:&lt;/p&gt;
&lt;div id="graph_15" style="width: 600px; height: 400px;"&gt;&lt;/div&gt;
&lt;p&gt;&lt;input id="button_graph_15" type="button" value="Logarithmic scale"&gt;
&lt;script type="text/javascript"&gt;function draw_graph_15(){var graph=new google.visualization.LineChart(document.getElementById('graph_15'));var data=google.visualization.arrayToDataTable([['x','auto_unlink_list','safe_list','normal_ilist','list'],['100000',3263,3415,3172,4444],['200000',9467,9434,9513,8855],['300000',13996,13888,14227,13379],['400000',18181,18458,18255,17684],['500000',22751,23292,22956,22067],['600000',27371,27511,27329,25995],['700000',31236,31389,31404,31164],['800000',35749,35970,36132,35224],['900000',39972,40684,40549,39786],['1000000',45119,45124,44840,43937],]);var options={curveType:"function",animation:{duration:1200,easing:"in"},title:"write - Normal&lt;1024u&gt;",width:'600px',height:'400px',hAxis:{title:"Number of elements",slantedText:true},vAxis:{title:"us",viewWindow:{min:0}}};graph.draw(data,options);var button=document.getElementById('button_graph_15');button.onclick=function(){if(options.vAxis.logScale){button.value="Logarithmic Scale";}else{button.value="Normal scale";}options.vAxis.logScale=!options.vAxis.logScale;graph.draw(data,options);};}&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;This time, the intrusive version is not faster anymore than the standard list.&lt;/p&gt;
&lt;p&gt;We have seen that when write is made to the data, intrusive list are better than list. The margin is higher than when doing only iteration.&lt;/p&gt;
&lt;!--nextpage--&gt;

&lt;h3&gt;Reverse the list&lt;/h3&gt;

&lt;p&gt;Let's test something more useful with a reverse operation. The reverse member function is used to reverse all the containers.&lt;/p&gt;
&lt;p&gt;Let's see how they perform:&lt;/p&gt;
&lt;div id="graph_16" style="width: 600px; height: 400px;"&gt;&lt;/div&gt;
&lt;p&gt;&lt;input id="button_graph_16" type="button" value="Logarithmic scale"&gt;
&lt;script type="text/javascript"&gt;function draw_graph_16(){var graph=new google.visualization.LineChart(document.getElementById('graph_16'));var data=google.visualization.arrayToDataTable([['x','auto_unlink_list','safe_list','normal_ilist','list'],['100000',366,410,390,372],['200000',761,892,758,867],['300000',1278,1354,1308,2062],['400000',2313,2348,2324,3083],['500000',3265,3297,3300,3994],['600000',4036,4171,4063,4890],['700000',4603,4575,4689,6052],['800000',5344,5241,5321,6682],['900000',6107,5912,6251,7623],['1000000',6725,6626,6663,8548],]);var options={curveType:"function",animation:{duration:1200,easing:"in"},title:"reverse - Normal&lt;8u&gt;",width:'600px',height:'400px',hAxis:{title:"Number of elements",slantedText:true},vAxis:{title:"us",viewWindow:{min:0}}};graph.draw(data,options);var button=document.getElementById('button_graph_16');button.onclick=function(){if(options.vAxis.logScale){button.value="Logarithmic Scale";}else{button.value="Normal scale";}options.vAxis.logScale=!options.vAxis.logScale;graph.draw(data,options);};}&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;The intrusive versions are about 25% faster than standard list. Even if reversal does not need to access the values, the pointers of the intrusive lists have a better locality than the one of a list that can be dispersed through memory.&lt;/p&gt;
&lt;div id="graph_17" style="width: 600px; height: 400px;"&gt;&lt;/div&gt;
&lt;p&gt;&lt;input id="button_graph_17" type="button" value="Logarithmic scale"&gt;
&lt;script type="text/javascript"&gt;function draw_graph_17(){var graph=new google.visualization.LineChart(document.getElementById('graph_17'));var data=google.visualization.arrayToDataTable([['x','auto_unlink_list','safe_list','normal_ilist','list'],['100000',585,563,601,1057],['200000',1903,1902,2011,3043],['300000',4121,4041,4049,4671],['400000',5291,5352,5275,6504],['500000',6831,6711,6584,8273],['600000',7980,8113,8105,9900],['700000',9366,9216,9426,11612],['800000',10680,10622,10602,13377],['900000',11917,11908,11915,15140],['1000000',13442,13239,13268,16718],]);var options={curveType:"function",animation:{duration:1200,easing:"in"},title:"reverse - Normal&lt;32u&gt;",width:'600px',height:'400px',hAxis:{title:"Number of elements",slantedText:true},vAxis:{title:"us",viewWindow:{min:0}}};graph.draw(data,options);var button=document.getElementById('button_graph_17');button.onclick=function(){if(options.vAxis.logScale){button.value="Logarithmic Scale";}else{button.value="Normal scale";}options.vAxis.logScale=!options.vAxis.logScale;graph.draw(data,options);};}&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;The performance improved a bit, to 30% improvement for an intrusive list.&lt;/p&gt;
&lt;p&gt;Let's see if this continue:&lt;/p&gt;
&lt;div id="graph_18" style="width: 600px; height: 400px;"&gt;&lt;/div&gt;
&lt;p&gt;&lt;input id="button_graph_18" type="button" value="Logarithmic scale"&gt;
&lt;script type="text/javascript"&gt;function draw_graph_18(){var graph=new google.visualization.LineChart(document.getElementById('graph_18'));var data=google.visualization.arrayToDataTable([['x','auto_unlink_list','safe_list','normal_ilist','list'],['100000',2901,2901,2676,4562],['200000',5889,5942,5613,9059],['300000',8696,8618,8372,13501],['400000',11344,11597,11039,17985],['500000',14431,14123,13954,22546],['600000',17084,16955,16605,27246],['700000',19563,19795,19431,31866],['800000',22806,22428,22092,36645],['900000',25553,25283,25003,41025],['1000000',28049,28174,27590,45780],]);var options={curveType:"function",animation:{duration:1200,easing:"in"},title:"reverse - Normal&lt;128u&gt;",width:'600px',height:'400px',hAxis:{title:"Number of elements",slantedText:true},vAxis:{title:"us",viewWindow:{min:0}}};graph.draw(data,options);var button=document.getElementById('button_graph_18');button.onclick=function(){if(options.vAxis.logScale){button.value="Logarithmic Scale";}else{button.value="Normal scale";}options.vAxis.logScale=!options.vAxis.logScale;graph.draw(data,options);};}&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;It did, the intrusive list is more than 40% faster than the standard list !&lt;/p&gt;
&lt;p&gt;What happens a bigger one:&lt;/p&gt;
&lt;div id="graph_19" style="width: 600px; height: 400px;"&gt;&lt;/div&gt;
&lt;p&gt;&lt;input id="button_graph_19" type="button" value="Logarithmic scale"&gt;
&lt;script type="text/javascript"&gt;function draw_graph_19(){var graph=new google.visualization.LineChart(document.getElementById('graph_19'));var data=google.visualization.arrayToDataTable([['x','auto_unlink_list','safe_list','normal_ilist','list'],['100000',4723,4823,4585,4373],['200000',11566,11566,11842,8704],['300000',17471,17377,17587,12985],['400000',22778,22867,22866,17452],['500000',28548,28434,28837,21357],['600000',34005,34089,33913,25907],['700000',39189,39235,39284,30398],['800000',45186,44900,44838,34632],['900000',50337,50529,50677,38540],['1000000',56045,56026,56007,42867],]);var options={curveType:"function",animation:{duration:1200,easing:"in"},title:"reverse - Normal&lt;1024u&gt;",width:'600px',height:'400px',hAxis:{title:"Number of elements",slantedText:true},vAxis:{title:"us",viewWindow:{min:0}}};graph.draw(data,options);var button=document.getElementById('button_graph_19');button.onclick=function(){if(options.vAxis.logScale){button.value="Logarithmic Scale";}else{button.value="Normal scale";}options.vAxis.logScale=!options.vAxis.logScale;graph.draw(data,options);};}&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;The lines have been interchanged! This time the standard list is about 25% faster than the intrusive versions. This time, the better locality of the intrusive versions is not a gain but a loss.&lt;/p&gt;
&lt;p&gt;It is logical that the margin decrease with very big objects during reversal. Indeed, each element is very close one to another, but the pairs of pointers are separated by the size of the data type. The bigger the data type, the higher distance between the pointers and so the worse spatial locality for the pointers. However, I do not explain why there is this big difference...&lt;/p&gt;
&lt;p&gt;The performance of intrusive list are clearly interesting for reversing collection of small data types. However, it seems that for high data types, the standard list is faster.&lt;/p&gt;
&lt;!--nextpage--&gt;

&lt;h3&gt;Sort the list&lt;/h3&gt;

&lt;p&gt;Let's continue with an even more interesting operation, sorting the list. All the versions are sorted with the sort member function.&lt;/p&gt;
&lt;div id="graph_20" style="width: 600px; height: 400px;"&gt;&lt;/div&gt;
&lt;p&gt;&lt;input id="button_graph_20" type="button" value="Logarithmic scale"&gt;
&lt;script type="text/javascript"&gt;function draw_graph_20(){var graph=new google.visualization.LineChart(document.getElementById('graph_20'));var data=google.visualization.arrayToDataTable([['x','auto_unlink_list','safe_list','normal_ilist','list'],['100000',16314,16503,16364,24992],['200000',38251,37599,38206,62834],['300000',63573,63521,63878,112848],['400000',90236,88561,88996,168037],['500000',114442,114456,116137,236389],['600000',167279,165879,166617,324302],['700000',190762,190586,190292,377142],['800000',223884,223900,224622,477313],['900000',255248,252795,253070,540602],['1000000',287262,286842,288404,614163],]);var options={curveType:"function",animation:{duration:1200,easing:"in"},title:"sort - Normal&lt;8u&gt;",width:'600px',height:'400px',hAxis:{title:"Number of elements",slantedText:true},vAxis:{title:"ms",viewWindow:{min:0}}};graph.draw(data,options);var button=document.getElementById('button_graph_20');button.onclick=function(){if(options.vAxis.logScale){button.value="Logarithmic Scale";}else{button.value="Normal scale";}options.vAxis.logScale=!options.vAxis.logScale;graph.draw(data,options);};}&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;The intrusive versions are really interesting, being twice faster than a standard list.&lt;/p&gt;
&lt;p&gt;Let's see with a see a higher data type:&lt;/p&gt;
&lt;div id="graph_21" style="width: 600px; height: 400px;"&gt;&lt;/div&gt;
&lt;p&gt;&lt;input id="button_graph_21" type="button" value="Logarithmic scale"&gt;
&lt;script type="text/javascript"&gt;function draw_graph_21(){var graph=new google.visualization.LineChart(document.getElementById('graph_21'));var data=google.visualization.arrayToDataTable([['x','auto_unlink_list','safe_list','normal_ilist','list'],['100000',25335,25030,25318,31655],['200000',67224,65937,67185,80637],['300000',118284,116947,119686,139629],['400000',169014,165868,169723,194916],['500000',208261,208245,209291,248475],['600000',294572,287231,294284,339917],['700000',337154,332205,338323,389665],['800000',401654,393743,401249,461721],['900000',440058,434855,440984,506999],['1000000',494861,491360,497710,578176],]);var options={curveType:"function",animation:{duration:1200,easing:"in"},title:"sort - Normal&lt;128u&gt;",width:'600px',height:'400px',hAxis:{title:"Number of elements",slantedText:true},vAxis:{title:"ms",viewWindow:{min:0}}};graph.draw(data,options);var button=document.getElementById('button_graph_21');button.onclick=function(){if(options.vAxis.logScale){button.value="Logarithmic Scale";}else{button.value="Normal scale";}options.vAxis.logScale=!options.vAxis.logScale;graph.draw(data,options);};}&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;The difference is decreasing to about 20%.&lt;/p&gt;
&lt;p&gt;Increasing it again:&lt;/p&gt;
&lt;div id="graph_22" style="width: 600px; height: 400px;"&gt;&lt;/div&gt;
&lt;p&gt;&lt;input id="button_graph_22" type="button" value="Logarithmic scale"&gt;
&lt;script type="text/javascript"&gt;function draw_graph_22(){var graph=new google.visualization.LineChart(document.getElementById('graph_22'));var data=google.visualization.arrayToDataTable([['x','auto_unlink_list','safe_list','normal_ilist','list'],['100000',31568,33319,32201,40331],['200000',82407,85932,83987,97310],['300000',143651,150155,144553,163818],['400000',202050,209178,203821,232728],['500000',250514,256374,253415,289493],['600000',345760,351034,348564,391229],['700000',397848,402385,402371,454434],['800000',471832,479947,477681,538873],['900000',518542,527961,524002,596696],['1000000',583622,596696,591025,672353],]);var options={curveType:"function",animation:{duration:1200,easing:"in"},title:"sort - Normal&lt;1024u&gt;",width:'600px',height:'400px',hAxis:{title:"Number of elements",slantedText:true},vAxis:{title:"ms",viewWindow:{min:0}}};graph.draw(data,options);var button=document.getElementById('button_graph_22');button.onclick=function(){if(options.vAxis.logScale){button.value="Logarithmic Scale";}else{button.value="Normal scale";}options.vAxis.logScale=!options.vAxis.logScale;graph.draw(data,options);};}&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;It decreased again to 18%.&lt;/p&gt;
&lt;p&gt;For sort operations, the intrusive versions are clearly interesting, especially for small data types.&lt;/p&gt;
&lt;!--nextpage--&gt;

&lt;h3&gt;Random insert into the list&lt;/h3&gt;

&lt;p&gt;The last operation that we will test is the random insert. I have to say that this test is not fair. Indeed, in an intrusive list, from an object we can directly get an iterator and insert at a random position. For a standard list, we have to find the iterator by linear search. I think that it is still important because it is one of the advantages of an intrusive container.&lt;/p&gt;
&lt;div id="graph_23" style="width: 600px; height: 400px;"&gt;&lt;/div&gt;
&lt;p&gt;&lt;input id="button_graph_23" type="button" value="Logarithmic scale"&gt;
&lt;script type="text/javascript"&gt;function draw_graph_23(){var graph=new google.visualization.LineChart(document.getElementById('graph_23'));var data=google.visualization.arrayToDataTable([['x','auto_unlink_ilist','safe_ilist','normal_ilist','list'],['10000',42,46,41,27729],['20000',49,66,45,48736],['30000',64,66,47,62440],['40000',54,53,48,75253],['50000',59,54,49,88493],['60000',67,49,63,104516],['70000',50,53,50,115514],['80000',55,50,50,128950],['90000',51,51,55,144367],['100000',52,52,76,152721],]);var options={curveType:"function",animation:{duration:1200,easing:"in"},title:"random_insert - Normal&lt;8u&gt;",width:'600px',height:'400px',hAxis:{title:"Number of elements",slantedText:true},vAxis:{title:"us",viewWindow:{min:0}}};graph.draw(data,options);var button=document.getElementById('button_graph_23');button.onclick=function(){if(options.vAxis.logScale){button.value="Logarithmic Scale";}else{button.value="Normal scale";}options.vAxis.logScale=!options.vAxis.logScale;graph.draw(data,options);};}&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;It is very clear that the performance are much better but it is logical because we are comparing something in O(1) versus something in O(n).&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;

&lt;p&gt;In conclusion, intrusive lists are almost always faster than a standard list. However, on my computer and with GCC, the difference is not always very important. It can brings about 20%-30% on some workloads but most likely around 15%. Even if not negligible, it is not a huge improvement. I would have thought that intrusive lists were faster by an higher margin. On some operations like sort, it is clearly more interesting. It has a better data locality than standard list.&lt;/p&gt;
&lt;p&gt;It is also more interesting to fill the collection, because no memory allocation is involved. But of course, you need to take care of memory allocation by yourself, for example in a vector like here or by dynamically allocating the objects one after one. This has also a cost that is not counted in the benchmark.&lt;/p&gt;
&lt;p&gt;If you really have to use a linked list and performance is critical, I advice you to use Boost intrusive list. If performance is not really critical, it is not perhaps not interesting because of the increased complexity.&lt;/p&gt;
&lt;p&gt;There are situations when only intrusive lists can work. If you want the same object to be present in two different list, you can use boost intrusive list with several member hooks, which is not possible with standard list because only a copy is stored, not the object itself. The same is true for objects that are non-copyable, only intrusive list can handle them. And finally, with intrusive lists you can directly get an iterator to an object in O(1) if you have a reference to an object. For a standard list, you have to iterate through the list to find the object. Sometimes, it can be very useful.&lt;/p&gt;
&lt;p&gt;If you are interested, the Boost documentation provides also a &lt;a href="http://www.boost.org/doc/libs/1_52_0/doc/html/intrusive/performance.html" title="Boost Intrusive Performance"&gt;performance benchmark for intrusive list&lt;/a&gt;, but it is very old (GCC 4.1.2). It is interesting to see that the results are better for intrusive lists than on my benchmark. I do not know if it comes from the processor, the memory or from the compiler.&lt;/p&gt;
&lt;p&gt;I hope you found this benchmark interesting. If you have questions, comments, ideas or whatever to say about this benchmark, don't hesitate to comment. I would be glad to answer you :) The same if you find errors in this article. If you have different results, don't hesitate to comment as well.&lt;/p&gt;
&lt;p&gt;The code source of the benchmark is available online: https://github.com/wichtounet/articles/blob/master/src/intrusive_list/bench.cpp&lt;/p&gt;
&lt;script type="text/javascript"&gt;function draw_visualization(){draw_graph_0();draw_graph_1();draw_graph_2();draw_graph_3();draw_graph_4();draw_graph_5();draw_graph_6();draw_graph_7();draw_graph_8();draw_graph_9();draw_graph_10();draw_graph_11();draw_graph_12();draw_graph_13();draw_graph_14();draw_graph_15();draw_graph_16();draw_graph_17();draw_graph_18();draw_graph_19();draw_graph_20();draw_graph_21();draw_graph_22();draw_graph_23();} google.setOnLoadCallback(draw_visualization);&lt;/script&gt;</description><category>Benchmark</category><category>Boost</category><category>C++</category><category>C++11</category><category>Performances</category><guid>https://baptiste-wicht.com/posts/2012/12/cpp-benchmark-std-list-boost-intrusive-list.html</guid><pubDate>Wed, 12 Dec 2012 07:53:17 GMT</pubDate></item><item><title>Run your Boost Tests in parallel with CMake</title><link>https://baptiste-wicht.com/posts/2012/10/run-boost-test-parallel-cmake.html</link><dc:creator>Baptiste Wicht</dc:creator><description>&lt;p&gt;I was looking for a Test Library to run eddic tests in parallel to replace Boost Test Library. I posted my question on StackOverflow and an awesome solution has been posted. With CMake and a little CMake additional file, it is possible to run the tests written with Boost Test Library in parallel without changing anything in the tests code !&lt;/p&gt;
&lt;p&gt;CTest is the test runner that is shipped with CMake. This runner can run tests in parallel using the -j X option (X is the numbers of threads). However, it can only run the tests that are declared in the CMakeLists.txt file. In my case, this means only one (the executable with Boost Test Library). If you have T tests, a solution would be create T executable files. Then, they can be run in parallel by ctest. However, this is not very practical. The solution proposed in this article is better. &lt;/p&gt;
&lt;h3&gt;Integrate Boost Test Library in CMake&lt;/h3&gt;

&lt;p&gt;Ryan Pavlik provides a series of CMake modules in its Github repository. One of this module is named BoostTestTargets. It automatically generates the CTest commands to run all the tests that you have. The small drawback is that you to list all the tests. &lt;/p&gt;
&lt;p&gt;To start, you have to download these files: &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;a href="https://github.com/rpavlik/cmake-modules/raw/master/BoostTestTargets.cmake" title="BoostTestTargets.cmake"&gt;BoostTestTargets.cmake&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://github.com/rpavlik/cmake-modules/raw/master/GetForceIncludeDefinitions.cmake" title="GetForceIncludeDefinitions.cmake"&gt;GetForceIncludeDefinitions.cmake&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://github.com/rpavlik/cmake-modules/raw/master/CopyResourcesToBuildTree.cmake" title="CopyResourcesToBuildTree.cmake"&gt;CopyResourcesToBuildTree.cmake&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://github.com/rpavlik/cmake-modules/blob/master/BoostTestTargetsStatic.h" title="BoostTestTargetsStatic.h"&gt;BoostTestTargetsStatic.h&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://github.com/rpavlik/cmake-modules/blob/master/BoostTestTargetsDynamic.h" title="BoostTestTargetsDynamic.h"&gt;BoostTestTargetsDynamic.h&lt;/a&gt;&lt;/li&gt;
    &lt;li&gt;&lt;a href="https://github.com/rpavlik/cmake-modules/blob/master/BoostTestTargetsIncluded.h" title="BoostTestTargetsIncluded.h"&gt;BoostTestTargetsIncluded.h&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These files must be placed next to your CMakeLists.txt file. Then, you have to modify your CMakeLists.txt file to enable testing and enable the new module. For example, if you have two test suites and five tests in each:  &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nb"&gt;INCLUDE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;CTest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;ENABLE_TESTING&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;GLOB_RECURSE&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;test_files&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;test/*&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;BoostTestTargets.cmake&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;add_boost_test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;eddic_boost_test&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;SOURCES&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;test_files&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;TESTS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;TestSuiteA/test_1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;TestSuiteA/test_2&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;TestSuiteA/test_3&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;TestSuiteA/test_4&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;TestSuiteA/test_5&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;TestSuiteB/test_1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;TestSuiteB/test_2&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;TestSuiteB/test_3&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;TestSuiteB/test_4&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;TestSuiteB/test_5&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;All the test files are searched in the test directory and used in the SOURCES variable. Then all the tests are declared. &lt;/p&gt;
&lt;p&gt;The main test file has to include a specific header file:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="cp"&gt;#define BOOST_TEST_MODULE eddic_test_suite&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cpf"&gt;&amp;lt;BoostTestTargetConfig.h&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This file will be automatically detected by BoostTestTargets and configured correctly. And that's it !&lt;/p&gt;
&lt;p&gt;You can run CMake again in your build directory to use the new test system: &lt;/p&gt;
&lt;p&gt;[bash]cmake .[/bash]&lt;/p&gt;
&lt;p&gt;If the configuration has been successful, you will see a message indicating that. For example, I see that: &lt;/p&gt;
&lt;pre&gt;-- Test 'eddic_boost_test' uses the CMake-configurable form of the boost test framework - congrats! (Including File: /home/wichtounet/dev/eddi/eddic/test/IntegrationTests.cpp)
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/ramdrive/dev/eddic&lt;/pre&gt;

&lt;h3&gt;Run tests in parallel&lt;/h3&gt;

&lt;p&gt;You can then run your tests in parallel with ctest. For instance, with 9 threads: &lt;/p&gt;
&lt;pre&gt;ctest -j 8&lt;/pre&gt;

&lt;p&gt;In my case, my tests are completed 6x faster ! This is very valuable when you often run your tests. &lt;/p&gt;
&lt;p&gt;For more information on how to integrate your Boost Test Library tests with CMake, you can consult the &lt;a href="https://github.com/rpavlik/cmake-modules/" title="cmake-modules Github repository"&gt;The cmake-modules repository&lt;/a&gt;&lt;/p&gt;</description><category>Boost</category><category>C++</category><category>cmake</category><category>Concurrency</category><category>EDDI</category><category>Performances</category><category>Tests</category><guid>https://baptiste-wicht.com/posts/2012/10/run-boost-test-parallel-cmake.html</guid><pubDate>Mon, 15 Oct 2012 06:57:43 GMT</pubDate></item><item><title>Manage command-line options with Boost Program Options</title><link>https://baptiste-wicht.com/posts/2012/07/manage-command-line-boost-program-options.html</link><dc:creator>Baptiste Wicht</dc:creator><description>&lt;p&gt;In command-line program, we often faces problems with the management of command-line options. When you have a few options, it's not a problem. But when writing complex programs with tens of options (or hundreds), it starts to be too complicated to manage by hand. That's where &lt;strong&gt;Boost Program Options&lt;/strong&gt; enters the game!&lt;/p&gt;
&lt;p&gt;Boost Program Options is one of the Boost C++ Libraries. It is a very powerful library to handle command-line options. You define all the options of the program and then Boost Program Options takes care of all. It parses the command line, handles errors, gets values and even displays help. It is not a perfect library. But it is very complete that will answer most of the common needs. &lt;/p&gt;
&lt;p&gt;This library is not header-only. You will need to build the library and link your program with the library. &lt;/p&gt;
&lt;h4&gt;Getting started&lt;/h4&gt;

&lt;p&gt;In this article, I will use &lt;em&gt;po&lt;/em&gt; as an abbreviation of boost::program_options and all source will contains this namespace alias:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;namespace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;po&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nn"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;program_options&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;First of all, it is necessary to create an instance of po::option_description:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;po&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;options_description&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MyTool Usage"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_options&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"help"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Display this help message"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Display the version number"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The parameter to the constructor is the title of the options. To add options, you use the add_options() function and append all your options, each one surrounded with parenthesis. Here, we declared two options (help and version). They can be set with &lt;em&gt;--help&lt;/em&gt; and &lt;em&gt;--version&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;Then, you can parse the command line by declaring a po::variables_map to store the variables and parse the command line into that storage: &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;po&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;variables_map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;po&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;po&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;command_line_parser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;po&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, you can easily verify if an option has been set by using the &lt;em&gt;count(const std::string&amp;amp; name)&lt;/em&gt; function on the &lt;em&gt;vm&lt;/em&gt; object: &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"help"&lt;/span&gt;&lt;span class="p"&gt;)){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can use &lt;em&gt;operator on the description to output all the options of program. &lt;/em&gt;&lt;/p&gt;
&lt;h4&gt;Short options&lt;/h4&gt;

&lt;p&gt;By default, all the options are accessed by using -- in front of them. You can also specify a short version for each option: &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_options&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"help,h"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Display this help message"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"version,v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Display the version number"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With that, you can display with either --help or -h. Even if you select help with -h, you can still verify if help has been set with count("help"). &lt;/p&gt;
&lt;h4&gt;Option with value&lt;/h4&gt;

&lt;p&gt;Boost Program Options can also handle option that need a specific value. Lets add a &lt;i&gt;compression&lt;/i&gt; option:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_options&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"help,h"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Display this help message"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"compression,c"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;po&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Compression level"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"version,v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Display the version number"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can then get the value of option easily: &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"compression"&lt;/span&gt;&lt;span class="p"&gt;)){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Compression level "&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"compression"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;as&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For the story, the option value are stored as boost::any. You can get the value of the option by using operator[] on the po::variables_map. You can get the value type with the as function with the type you need. &lt;/p&gt;
&lt;p&gt;On the command line, the value can be set with --compression 10, -c 10 or -c10. &lt;/p&gt;
&lt;p&gt;You can also configure a default value for an option:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_options&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"help,h"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Display this help message"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"compression,c"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;po&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;default_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Compression level"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"version,v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Display the version number"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With that, if the option is not set on the command line, the option has the specified value. With that, the option is always defined. &lt;/p&gt;
&lt;p&gt;Finally, you can also set an implicit value. This is the value of the option is the option is set to the command line without a value (--compression or -c): &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_options&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"help,h"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Display this help message"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"compression,c"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;po&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;default_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;implicit_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Compression level"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"version,v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Display the version number"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Positional options&lt;/h4&gt;

&lt;p&gt;It is often convenient to have a list of files on the command line. These options does not have a name. In Boost Program Options, these options are called positional options. You have to declare them in the describe as any other action. For example, for a list of files: &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_options&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"help,h"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Display this help message"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"compression,c"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;po&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;default_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;implicit_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="s"&gt;"Compression level"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"input-files"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;po&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Input files"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"version,v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Display the version number"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, you have to declare it as positional and then finally specify it when parsing the command-line: &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;po&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;positional_options_description&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"input-files"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;-1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;po&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;variables_map&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;po&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;po&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;command_line_parser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;positional&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;po&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The positional options values are retrieved the exact same way as other options: &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"input-files"&lt;/span&gt;&lt;span class="p"&gt;)){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"input-files"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;as&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;"Input file "&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Wrap-Up&lt;/h4&gt;

&lt;p&gt;In this article, we saw the most important aspects of Boost Program Options. With these notions, you can start using this great library. If you need more information about the library, you can read &lt;a href="http://www.boost.org/doc/libs/1_50_0/doc/html/program_options.html" title="Boost Program Options documentation"&gt;the official documentation&lt;/a&gt; that is very well made. &lt;/p&gt;
&lt;p&gt;You can download the final sources of this article on Github: &lt;a href="https://github.com/wichtounet/articles/blob/master/src/boost_po/v1.cpp" title="Source file for this article"&gt;v1.cpp&lt;/a&gt;&lt;/p&gt;</description><category>Boost</category><category>C++</category><guid>https://baptiste-wicht.com/posts/2012/07/manage-command-line-boost-program-options.html</guid><pubDate>Thu, 19 Jul 2012 06:19:37 GMT</pubDate></item><item><title>Use Boost enable_if to handle ambiguous function overload return types</title><link>https://baptiste-wicht.com/posts/2012/01/boost-enable_if-handle-ambiguous-function-overload-void.html</link><dc:creator>Baptiste Wicht</dc:creator><description>&lt;p&gt;The title is not really clear but I didn't found a better one. The example will be clearer (I hope). In EDDI, I had this little function : &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Visitor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Visitable&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Visitor&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;visitor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Visitable&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;visitable&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;visitor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;visitable&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For the record, this function is only invoking a specific operator of a visitor. The problem was that I wanted this function to handle also non-void visitors. The visitor in question has a &lt;strong&gt;result_type&lt;/strong&gt; typedef indicating the return type of the visit. The naive version cannot work : &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Visitor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Visitable&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Visitor&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;result_type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Visitor&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;visitor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Visitable&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;visitable&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;visitor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;visitable&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Visitor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Visitable&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Visitor&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;visitor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Visitable&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;visitable&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;visitor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;visitable&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The problem here is that there are ambiguities for overload resolution because the return type is not considered in this resolution. What we want is that the overload resolution does not consider the function returning something (the first one). And that's here that Boost can help, specifically the &lt;strong&gt;Boost enable_if&lt;/strong&gt; library. This function allows to enable of disable some function template of function class based on a boolean condition. In our case, we want to disable the function is the return type is void. So, we will use the &lt;strong&gt;boost::disable_if&lt;/strong&gt; template to disable it. This template has to parameter B and T. When B is true, the template is evaluated to T, otherwise there is an error used for SFINAE (Substitution failure is not an error) To test if the return type is void, we will use Boost type_traits, specifically the &lt;strong&gt;boost::is_void&lt;/strong&gt; template. &lt;/p&gt;
&lt;p&gt;Here is the version using disable_if : &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Visitor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Visitable&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;disable_if&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;is_void&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Visitor&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;result_type&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Visitor&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;result_type&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;
&lt;span class="n"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Visitor&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;visitor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Visitable&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;visitable&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;visitor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;visitable&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Visitor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Visitable&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Visitor&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;visitor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Visitable&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;visitable&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;visitor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;visitable&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With that, you can call the visitor with a void return type. However, it's not enough. Indeed, the call is still ambiguous when the return type is not void. So we have to enable the second function only if the return type is void : &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Visitor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Visitable&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;disable_if&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;is_void&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Visitor&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;result_type&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Visitor&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;result_type&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;
&lt;span class="n"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Visitor&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;visitor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Visitable&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;visitable&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;visitor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;visitable&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Visitor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Visitable&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;enable_if&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;is_void&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Visitor&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;result_type&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;Visitor&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;result_type&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;
&lt;span class="n"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Visitor&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;visitor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Visitable&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;amp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;visitable&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;visitor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;visitable&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With that, you can call the function with both visitors and the good function will be chosen depending on the result type of the visitor. &lt;/p&gt;
&lt;p&gt;I hope this example of using Boost enable_if will help you when you face similar problems.&lt;/p&gt;</description><category>Boost</category><category>C++</category><category>templates</category><guid>https://baptiste-wicht.com/posts/2012/01/boost-enable_if-handle-ambiguous-function-overload-void.html</guid><pubDate>Fri, 13 Jan 2012 07:51:25 GMT</pubDate></item><item><title>Boost 1.48.0 has been released </title><link>https://baptiste-wicht.com/posts/2011/11/boost-1-48-0-has-been-released.html</link><dc:creator>Baptiste Wicht</dc:creator><description>&lt;p&gt;A new version of Boost is available : &lt;a href="http://www.boost.org/users/history/version_1_48_0.html" title="Boost 1.48.0 Details"&gt;Boost 1.48.0&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This release includes three new libraries : Locale, Container and Move. &lt;/p&gt;
&lt;p&gt;A lot of bug have been fixed and there are also some changes in the existing libraries.&lt;/p&gt;</description><category>Boost</category><category>C++</category><category>Libraries</category><category>templates</category><guid>https://baptiste-wicht.com/posts/2011/11/boost-1-48-0-has-been-released.html</guid><pubDate>Tue, 15 Nov 2011 09:48:59 GMT</pubDate></item><item><title>Boost intrusive_ptr : faster shared pointer</title><link>https://baptiste-wicht.com/posts/2011/11/boost-intrusive_ptr.html</link><dc:creator>Baptiste Wicht</dc:creator><description>&lt;p&gt;This post will present the Boost intrusive_ptr and its usage in C++ programming. &lt;/p&gt;
&lt;p&gt;Recently, I took some time to optimize the parsing performances of the EDDI Compiler. The parsing phase creates a lot of nodes to fill the Abstract Syntax Tree. &lt;/p&gt;
&lt;p&gt;One of the way I found was to replace some shared_ptr by some intrusive_ptr of the Boost library. &lt;/p&gt;
&lt;p&gt;It's a faster alternative of shared_ptr. Like its name indicates, it's intrusive. The reference counter is included directely in the managed class, in the contrary of the shared_ptr where the reference counter has to be dynamically allocated to live aside the object. This leads to some performances improvement. Considering memory, the footprint of an intrusive_ptr is the same as the footprint of a raw pointer. This is not the case for the shared_ptr that have a pointer to the object, a pointer to the counter and the counter itself. &lt;/p&gt;
&lt;p&gt;For example, if you have a class X:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;X&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And you use it in your code using a shared_ptr : &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;shared_ptr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;and you want to use an intrusive_ptr, you have first to add a reference counter inside the X class : &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;X&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;references&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;references&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And you have to indicate to the intrusive_ptr where the reference counter can be found for this class : &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kr"&gt;inline&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;intrusive_ptr_add_ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;references&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;inline&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;intrusive_ptr_release&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;references&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And finally you can use the intrusive_ptr to replace your shared_ptr : &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;intrusive_ptr&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;cout&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The smart pointer itself can be used exactly the same way as a shared_ptr. If you have several classes that are managed using an intrusive_ptr, you can use a function template to tell Boost that all the reference counter are at the same place : &lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kr"&gt;inline&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;intrusive_ptr_add_ref&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;references&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typename&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="kr"&gt;inline&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;intrusive_ptr_release&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;references&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;expr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, the pointer is very intrusive and needs some boilerplate code added to your application, but it can leads to some interesting improvements for classes very often dynamically allocated. &lt;/p&gt;
&lt;p&gt;There is another advantage in using intrusive_ptr. As the reference counter is stored into the object itself, you can create several intrusive_ptr to the same object without any problem. This is not the case when you use a shared_ptr. Indeed, if you create two shared_ptr to the same dynamically allocated object, they will both have a different references counter and at the end, you will end up with an object being deleted twice. &lt;/p&gt;
&lt;p&gt;Of course, there are not only advantages. First of all, you have to declare a field in every classes that you want to manage using an intrusive_ptr and you have to declare functions to manage the reference. Then there are some disadvantages when using this pointer type compared to a shared_ptr : &lt;/p&gt;
&lt;ul&gt;
    &lt;li&gt;It's impossible to create a weak_ptr from a intrusive_ptr&lt;/li&gt;
    &lt;li&gt;Code redundancy, you have to copy the reference counter in every class that you want to use an intrusive_ptr with&lt;/li&gt;
    &lt;li&gt;You have to provide a function for every types that has to be used with intrusive_ptr (only two functions if you use the template versions of the two functions)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To conclude, the boost::intrusive_ptr can be a good replacement of std::shared_ptr in a performance critical application, but if you have no performances problem, do not use it because it makes your code less clear. If you are concerned by performances when using std::shared_ptr, consider also using std::make_shared to create your pointers, so that the reference counter and the object itself will be allocated at the same place and at the same time, resulting in better performances. Another case where it's interesting to use an intrusive_ptr is when dealing with libraries using a lot of raw pointers, because you can create several intrusive_ptr to the same raw pointer without any problem.&lt;/p&gt;
&lt;p&gt;For more information, you can consult &lt;a href="http://www.boost.org/doc/libs/1_47_0/libs/smart_ptr/intrusive_ptr.html" title="Boost intrusive_ptr official documentation"&gt;the official documentation&lt;/a&gt;.&lt;/p&gt;</description><category>Boost</category><category>C++</category><category>Performances</category><guid>https://baptiste-wicht.com/posts/2011/11/boost-intrusive_ptr.html</guid><pubDate>Mon, 14 Nov 2011 07:40:41 GMT</pubDate></item><item><title>eddic 0.5.1 : Better assembly generation and faster parsing</title><link>https://baptiste-wicht.com/posts/2011/11/eddic-0-5-1-better-assembly-generation-and-faster-parsing.html</link><dc:creator>Baptiste Wicht</dc:creator><description>&lt;p&gt;I'm very pleased to release the version 0.5.1 of the EDDI Compiler.&lt;/p&gt;
&lt;p&gt;It makes now a long time since the last version of eddic, but I started again working frequently on it. This version doesn't add any new feature to the language, but there are a lot of improvements in the compiler itself. &lt;/p&gt;
&lt;p&gt;First of all, the generated assembly has been improved a lot. I use now a intermediate representation of assembly and then the compiler is able to make more optimizations in its choice. This optimization is especially visible for integer computations. Before this, all the computations used stack operations and then we use almost only registers when it's possible. It's still not perfect, but it uses way less instructions. Moreover, this can enable me to write a 64 assembly code instead of 32 and provide both versions in the compiler. &lt;/p&gt;
&lt;p&gt;Another improvement is the speed of the parser. I now use Boost Spirit to parse the source file and construct an Abstract Syntax Tree. This parsing is very fast now (with some optimizations). Moreover, it will be easier to add new constructs later. &lt;/p&gt;
&lt;p&gt;I also improved the general performances at some places. I also use Boost Program Options to parse the command line options. &lt;/p&gt;
&lt;p&gt;In the next version (0.6.0), I will introduce arrays of int and strings and the foreach construct for array. I will also remove the dependency to malloc writing a memory allocation manager in assembly. I will also introduce warnings in the compiler. &lt;/p&gt;
&lt;p&gt;You can find the compiler sources on the Github repository : &lt;a title="EDDI COmpiler Repository" href="http://github.com/wichtounet/eddic"&gt;https://github.com/wichtounet/eddic&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;The compiler now needs Boost 1.47.0 to build. &lt;/p&gt;
&lt;p&gt;The exact version I refer to is the v0.5.1 available in the github tags or directly as the release branch.&lt;/p&gt;</description><category>Assembly</category><category>Boost</category><category>C++</category><category>EDDI</category><category>Performances</category><category>Releases</category><category>templates</category><guid>https://baptiste-wicht.com/posts/2011/11/eddic-0-5-1-better-assembly-generation-and-faster-parsing.html</guid><pubDate>Thu, 10 Nov 2011 03:33:32 GMT</pubDate></item><item><title>Diploma Thesis : Inlining Assistance for large-scale object-oriented applications</title><link>https://baptiste-wicht.com/posts/2011/10/diploma-thesis-inlining-assistance-for-large-scale-object-oriented-applications.html</link><dc:creator>Baptiste Wicht</dc:creator><description>&lt;div&gt;&lt;p&gt;One month ago, my diploma thesis has been accepted and I got my Bachelor of Science in Computer Science.&lt;/p&gt;
&lt;p&gt;I made my diploma thesis at Lawrence Berkeley National Laboratory, Berkeley, California. I was in the team responsible of the developmenet of the ATLAS Software for the LHC in Cern. The title of my thesis is &lt;strong&gt;Inlining Assistance for large-scale object-oriented applications&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The goal of this project was to create a C++ analyzer to find the best functions and call sites to inline. The input of the analyzer is a call graph generated by CallGrind of the Valgrind project.&lt;/p&gt;
&lt;p&gt;The functions and call sites to inline are computed using a heuristic, called the temperature. This heuristic is based on the cost of calling the given function, the frequency of calls and the size of the function. The cost of calling a function is based on the number of parameters, the virtuality of the function and the shared object the function is located in.&lt;/p&gt;
&lt;p&gt;The analyzer is also able to find clusters of call sites. A cluster is a set of hot call sites related to each other. It can also finds the functions that should be moved from one library to the other or the function that should not be virtual by testing the use of each function in a class hierarchy.&lt;/p&gt;
&lt;p&gt;To achieve this project, it has been necessary to study in details how a function is called on the Linux platform. The inlining optimization has also been studied to know what were the advantages and the problems of this technique.&lt;/p&gt;
&lt;p&gt;To retrieve the information about the sizes and the virtuality of the function, it has been necessary to read the shared libraries and executables files. For that, we used &lt;em&gt;libelf&lt;/em&gt;. The virtuality of a function is calculated by reading each virtual table and searching for the function in the virtual tables content.&lt;/p&gt;
&lt;p&gt;The graph manipulation is made by the &lt;em&gt;Boost Graph Library&lt;/em&gt;. As it was an advanced library, it has helped me improving my skills in specific topics like templates, traits or Template Metaprogramming.&lt;/p&gt;
&lt;p&gt;The analyzer is able to run on the Linux platform on any program that has been compiled using gcc.&lt;/p&gt;
&lt;p class="more"&gt;&lt;a href="https://baptiste-wicht.com/posts/2011/10/diploma-thesis-inlining-assistance-for-large-scale-object-oriented-applications.html"&gt;Read more…&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;</description><category>Boost</category><category>C++</category><category>Compilers</category><category>gcc</category><category>Linux</category><category>Optimization</category><category>Performances</category><category>Personal</category><guid>https://baptiste-wicht.com/posts/2011/10/diploma-thesis-inlining-assistance-for-large-scale-object-oriented-applications.html</guid><pubDate>Mon, 03 Oct 2011 06:44:17 GMT</pubDate></item></channel></rss>