Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Pete's answer explains the situation. Both templates for swap are equally favoured during the overload resolution steps, so the call is ambiguous - in <em>any</em> context where both namespaces are visible. Specialisation is the correct approach to this problem, however based on your errors you've forgotten to remove the offending template <code>Foo::swap</code> - see <a href="https://stackoverflow.com/questions/11562/how-to-overload-stdswap">here</a> for what your code should look like.</p> <p>Here's what everything looks like - I just replaced the <code>std</code> namespace with the <code>bar</code> namespace.</p> <pre><code>#include &lt;iostream&gt; namespace bar { //std namespace template&lt;typename T&gt; void swap(T s, T t){ std::cout &lt;&lt; "bar swap\n"; } template&lt;typename S&gt; struct vec { S s; void error() { swap(s, s); } };} namespace foo { //your namespace struct type {}; /*this template is not allowed/not a good idea because of exactly your problem template&lt;typename T&gt; void swap(T s, T t){ std::cout &lt;&lt; "foo swap\n"; } */ //you will have to rename foo::swap to something like this, and make it call //specialise std::swap for any types used in std containers, so that they called yuor //renamed foo::swap template&lt;typename T&gt; void swap_proxy(T s, T t){ std::cout &lt;&lt; "foo swap (via proxy) \n"; } } namespace bar { template&lt;&gt; void swap(foo::type s, foo::type t) { std::cout &lt;&lt; "foo swap\n"; } } int main() { //instead specialise std::swap with your type bar::vec&lt;foo::type&gt; myVec; myVec.error(); std::cout &lt;&lt; "Test\n"; operator&lt;&lt;(std::cout, "Test\n"); } </code></pre> <p>All that said I'll try and cook up a templated alternative - however it will call <code>std::swap</code> in std code (it will make <code>foo::swap</code> a worse alternative, so there will be no ambiguity.</p> <hr> <p>This avoids changing the name of swap, but still changes its definition slightly - although you shouldn't have to tamper with code inside swap, only code that calls will have to cast as explained</p> <pre><code>#include &lt;iostream&gt; namespace bar { //std namespace template&lt;typename T&gt; void swap(T s, T t){ std::cout &lt;&lt; "bar swap\n"; } template&lt;typename S&gt; struct vec { S s; void error() { swap(s, s); } };} namespace foo { //your namespace // Include this pattern (The infamous Curiously Recurring Template Pattern) in foo namespace template&lt;template&lt;class&gt; class Derived, typename t&gt; struct Base : public t { Base(){} Base(Derived&lt;t&gt; d){} }; template&lt;typename t&gt; struct Derived : public Base&lt;Derived, t&gt; {}; template&lt;class t&gt; using UnWrapped = Base&lt;Derived, t&gt;; template&lt;class t&gt; using Wrapped = Derived&lt;t&gt;; //we redefine swap to accept only unwrapped t's - meanwhile //we use wrapped t's in std::containers template&lt;typename T&gt; void swap(UnWrapped&lt;T&gt; s, UnWrapped&lt;T&gt; t){ std::cout &lt;&lt; "foo swap\n"; } struct type { }; } int main() { //use the wrapped type typedef foo::Wrapped&lt;foo::type&gt; WrappedType; typedef foo::UnWrapped&lt;foo::type&gt; UnWrappedType; bar::vec&lt;WrappedType&gt; myVec; //this is the function which makes the ambiguous call myVec.error(); //but instead calls bar::swap //but -- it calls foo swap outside of bar! - any you didn't //have to change the name of swap, only alter definition slightly swap(WrappedType(), WrappedType()); //safe outside of bar swap(UnWrappedType(), UnWrappedType()); //the following no longer works :/ //swap&lt;foo::type&gt;(foo::type(), foo::type()); //instead, yuo will have to cast to UnWrapped&lt;type&gt; } </code></pre>
 

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