Note that there are some explanatory texts on larger screens.

plurals
  1. POHow can I solve this ambiguousity wrt. mem_fun?
    primarykey
    data
    text
    <p>To practice, one of the topics I'm familiarizing myself with again is trees. The thing about depth-first search and breadth-first search is that they differ only in the choice of the data structure that backs the algorithm.</p> <p>I thought I could write a common tree search that I would feed either a stack (DFS) or a queue (BFS) using templates. <code>stack</code> and <code>queue</code> are nice enough that their adding and removing members have the same name. Unfortunately, the access function is once called <code>top</code> and <code>front</code> for the other. Because of this I did no quite arrive where I wanted. I didn't manage to do it without that lambda:</p> <pre><code>template&lt;typename T, typename D, typename G&gt; bool ts(Tree&lt;T&gt; const &amp; tree, T const value, D &amp; ds, G getter) { if (empty(tree)) { return false; } ds.push(tree.Root); while (!ds.empty()) { auto const current = getter(); ds.pop(); if (current-&gt;Value == value) { return true; } if (current-&gt;Left) { ds.push(current-&gt;Left); } if (current-&gt;Right) { ds.push(current-&gt;Right); } } return false; } template&lt;typename T&gt; bool dfs(Tree&lt;T&gt; const &amp; tree, T const value) { stack&lt;typename Tree&lt;T&gt;::Node const * const&gt; ds; return ts(tree, value, ds, [&amp;ds](){ return ds.top(); }); } template&lt;typename T&gt; bool bfs(Tree&lt;T&gt; const &amp; tree, T const value) { queue&lt;typename Tree&lt;T&gt;::Node const * const&gt; ds; return ts(tree, value, ds, [&amp;ds](){ return ds.front(); }); } </code></pre> <p>I though that I should be able to use <code>mem_fun</code> (or <code>mem_fun_ref</code>) to provide the respective access function. I tried</p> <pre><code>template&lt;typename T&gt; bool dfs(Tree&lt;T&gt; const &amp; tree, T const value) { typedef stack&lt;typename Tree&lt;T&gt;::Node const * const&gt; DataStructure; return ts(tree, value, DataStructure(), mem_fun(&amp;DataStructure::top)); } </code></pre> <p>But then the compiler complains about ambiguousity (between a <code>const</code> and a non-<code>const</code> version).</p> <p>So I searched the internets and learned that I should provide the template type explicitly.</p> <pre><code>template&lt;typename T&gt; bool dfs(Tree&lt;T&gt; const &amp; tree, T const value) { typedef stack&lt;typename Tree&lt;T&gt;::Node const * const&gt; DataStructure; return ts(tree, value, DataStructure(), mem_fun&lt;/*???*/&gt;(&amp;DataStructure::top)); } </code></pre> <p>Sadly, none of the many possibilities for <strong>???</strong> that I could come up with satisfied the compiler.</p> <p>Can someone give me a hint?</p> <hr> <p><strong>Update:</strong> Here a full working example (except if you define NO_LAMBDA):</p> <pre><code>#include &lt;iostream&gt; #include &lt;stack&gt; #include &lt;functional&gt; using namespace std; template&lt;typename T&gt; struct Tree { struct Node { T Value; Node * Left; Node * Right; Node(T value) : Value(value), Left(nullptr), Right(nullptr) {} virtual ~Node() { if (Left) delete Left; if (Right) delete Right; } }; Node * Root; Tree() : Root(nullptr) {} virtual ~Tree() { if (Root) delete Root; } }; template&lt;typename T&gt; void insert(typename Tree&lt;T&gt;::Node * node, T const &amp; value) { typename Tree&lt;T&gt;::Node ** selected = &amp;(value &lt; node-&gt;Value ? node-&gt;Left : node-&gt;Right); if (*selected) insert(*selected, value); else *selected = new typename Tree&lt;T&gt;::Node(value); } template&lt;typename T&gt; void insert(Tree&lt;T&gt; &amp; tree, T value) { if (!tree.Root) tree.Root = new typename Tree&lt;T&gt;::Node(value); else insert(tree.Root, value); } template&lt;typename T, typename D, typename G&gt; bool ts(Tree&lt;T&gt; const &amp; tree, T const value, D &amp; ds, G getter) { if (!tree.Root) return false; ds.push(tree.Root); while (!ds.empty()) { auto const current = getter(); ds.pop(); if (current-&gt;Value == value) return true; if (current-&gt;Left) ds.push(current-&gt;Left); if (current-&gt;Right) ds.push(current-&gt;Right); } return false; } template&lt;typename T&gt; bool dfs(Tree&lt;T&gt; const &amp; tree, T const value) { typedef typename Tree&lt;T&gt;::Node const * DataStructureContent; typedef stack&lt;DataStructureContent&gt; DataStructure; #ifdef NO_LAMBDA // With this defined, it breaks. return ts(tree, value, DataStructure(), mem_fun(static_cast&lt;DataStructureContent (DataStructure::*)() const&gt;(&amp;DataStructure::top))); #else // This works. DataStructure ds; return ts(tree, value, ds, [&amp;ds] () { return ds.top(); }); #endif } int main() { Tree&lt;int&gt; tree; insert(tree, 5); insert(tree, 2); insert(tree, 1); insert(tree, 3); insert(tree, 7); insert(tree, 6); insert(tree, 9); cout &lt;&lt; "DFS(7) -&gt; " &lt;&lt; dfs(tree, 7) &lt;&lt; endl; cout &lt;&lt; "DFS(8) -&gt; " &lt;&lt; dfs(tree, 8) &lt;&lt; endl; return 0; } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

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