Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I'll try to answer the question why a functor is used. It's just a guess of course, as I'm not the author of the code, but I saw discussions about it at least a few times and the consensus seems to be, that functors enable or at least make it easier to inline the comparison code. </p> <p>Functors are structs (or classes) and in general are more flexible than regular functions because they can have some members, that store some state, which can be used by operator(). In this case this advantage isn't used, so the functor was most probably used to enable (or help) in inlining or just because the author was used to this common pattern.</p> <p>Why would it help in inlining? Let's look at a simple example. Lets take <code>std::sort</code></p> <pre><code>template &lt;class RandomAccessIterator, class Compare&gt; void sort ( RandomAccessIterator first, RandomAccessIterator last, Compare comp ); </code></pre> <p>Imagine You want to sort <code>std::vector&lt;int&gt;</code> and You want to provide Your custom comparators.</p> <pre><code>struct MyStructComp1 { bool operator()(int lhs, int rhs) const { /*...*/} }; struct MyStructComp2 { bool operator()(int lhs, int rhs) const { /*...*/} }; bool myFunctComp1 (int lhs, int rhs) const { /*...*/} bool myFunctComp2 (int lhs, int rhs) const { /*...*/} </code></pre> <p>Now You can use the <code>sort</code> temeplate in the following ways</p> <pre><code>sort(myvector.begin(), myvector.end(), MyStructComp1()); // 1 sort(myvector.begin(), myvector.end(), MyStructComp2()); // 2 sort(myvector.begin(), myvector.end(), myFunctComp1); // 3 sort(myvector.begin(), myvector.end(), myFunctComp2); // 4 </code></pre> <p>Here are the function the compiler creates form the template</p> <pre><code>sort&lt;vector&lt;int&gt;::iterator, MyStrucComp1&gt; // 1 sort&lt;vector&lt;int&gt;::iterator, MyStrucComp2&gt; // 2 sort&lt;vector&lt;int&gt;::iterator, bool (*) (int lhs, int rhs)&gt; // 3, // 4 </code></pre> <p>Since the Compare parameter in the sort template is a type, and functors are types, the compiler creates a different function for every functor supplied as a template argument. <code>sort&lt;vector&lt;int&gt;::iterator, MyStrucComp1&gt;</code> and<br> <code>sort&lt;vector&lt;int&gt;::iterator, MyStrucComp2&gt;</code> are two different functions. So when <code>sort&lt;vector&lt;int&gt;::iterator, MyStrucComp1&gt;</code> is created, it is known exactly what the comparing code is and the comparator can be simply inlined.</p> <p>Functions <code>myFunctComp</code>1 and <code>myFunctComp2</code> however are of exactly the same type:<br> <code>bool (*) (int lhs, int rhs)</code> and the compiler creates one function <code>sort&lt;vector&lt;int&gt;::iterator, bool (*) (int lhs, int rhs)&gt;</code> for all comparing functions of type <code>bool (*) (int lhs, int rhs)</code>. I saw opinions, that inlining is possible anyway in this situation, but I have no idea how.</p> <p>It is possible to create templates with a pointer to function as a template parameter as it's a compile time constant, but it's ugly and constants can't be deduced from the function arguments. For example if <code>sort</code> was defined as:</p> <pre><code>template &lt;class RandomAccessIterator, bool (*comparer) (typename RandomAccessIterator::value_type, typename RandomAccessIterator::value_type)&gt; void sort ( RandomAccessIterator first, RandomAccessIterator last) {/* */} </code></pre> <p>You would have to call it like this</p> <pre><code>sort&lt;std::vector&lt;int&gt;::iterator, myFunctComp1&gt;(myvector.begin(), myvector.end()); </code></pre> <p>You would get a different sort for every comparing function, but functors are much more convenient.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload