#include <iostream>
#include <vector>
#include <type_traits> //needed for enable_if?
using namespace std;

template<class T> struct supports_iteration
{ 
private:
	typedef char yes[1];
	typedef char no[2];
	template <class C> static yes& foo(typename C::iterator*);
	template <class C> static no& foo(...);
public:
	static constexpr bool value = sizeof(foo<T>(0)) == sizeof(yes);
};


template<template <class, class> class C, class T, class A>
void DoSomething(C<T,A>& val)
{
	T* pT;
	cout << "did something!\n";
}

template<template <class, class> class C, class T, class A>
void DoSomethingSmartly(
	typename std::enable_if<
		supports_iteration<
			C<T,A>
		>::value
	>::type& val)
{
	T* pT;
	cout << "did something smartly!\n";
}

template<template <class, class> class C, class T, class A, 
    typename = decltype(
        declval<C<T,A>>().size()
        ,void()
    )
>
void DoSomethingReallySmartly(C<T,A>& val)
{
	T* pT;
	cout << "did something really smartly!\n";
}

int main() {
	// your code goes here
	vector<int> v{1,2,3,4,5};
	DoSomething(v);
	cout << "vector<int> supports_iteration? " << 
		boolalpha << supports_iteration<decltype(v)>::value << "!" << endl;
	//DoSomethingSmartly(v);// - fails!!
	//template argument deduction/substitution failed:
	//couldn't deduce template parameter ‘template<class, class> class C’  DoSomethingSmartly(v);
	DoSomethingReallySmartly(v);
	return 0;
}
