#include <iostream>

struct WidgetImpl
{
	int a, b, c, d;
};

class Widget
{
	WidgetImpl *impl;
public:
	void swap (Widget & other)
	{
		std::cout << "Really doing swap" << std::endl;
		using std::swap;
		swap (impl, other.impl);
	}
};

namespace std
{
	template<>
	void swap<Widget> (Widget& a,Widget& b)
	{
		std::cout << "Doing swap" << std::endl;
		a.swap(b);
	}
}

namespace Ti
{
	template <typename T>
	struct TidgetImpl
	{
		int a, b, c, d;
	};

	template <typename T>
	class Tidget
	{
		TidgetImpl<T> *impl;
	public:
		void swap (Tidget<T> & other)
		{
			std::cout << "Really doing template swap" << std::endl;
			using std::swap;
			swap (impl, other.impl);
		}
	};

}

namespace std
{
	using namespace Ti;
	template<typename T>
	void swap (Tidget<T>& a,Tidget<T>& b)
	{
		std::cout << "Doing template swap" << std::endl;
		a.swap(b);
	}
}

using namespace std;
using namespace Ti;

int main()
{
	Widget w1;
	Widget w2;

	swap(w1, w2);

	Tidget<int> t1;
	Tidget<int> t2;

	swap (t1, t2);
}

