Visual Studio でのSFINAE

Visual Studio 2013
（[C++11/14 Core Language Features in VS 2013 and the Nov 2013 CTP - Visual C++ Team Blog - Site Home - MSDN Blogs]( http://blogs.msdn.com/b/vcblog/archive/2013/12/02/c-11-14-core-language-features-in-vs-2013-and-the-nov-2013-ctp.aspx)）

Test6のみfatal errorを吐く
 
```c++
#include <iostream>
#include <type_traits>
struct C1{};

// 関数のオーバーロード
void f0(C1) { std::cout << "template" << std::endl; }

// テンプレートクラス内static関数
template< class T > struct T1;
template<> struct T1<C1>{
	struct Flag;
	static void f1() { std::cout << "template" << std::endl; }
};

// f0<T> が存在するかを調べる
template<typename T>
class ExistF0{
private:
	template<typename U>
	static auto check(U v) -> decltype(f0(v), std::true_type());
	static auto check(...) -> decltype(std::false_type());

public:
	typedef decltype(check(std::declval<T>())) type;
	static bool const value = type::value;
};

// T::f1 が存在するか調べる
template<typename T>
class HasF1{
private:
	template<typename U>
	static auto check(U v) -> decltype(T1<U>::f1, std::true_type());
	static auto check(...) -> decltype(std::false_type());

public:
	typedef decltype(check(std::declval<T>())) type;
	static bool const value = type::value;
};

//////////

template<class T> void test1(T v, decltype(f0(std::declval<T>())) * = 0) { f0(v); }
void test1(double) { std::cout << "not template" << std::endl; }

template<class T> void test2(T, decltype(T1<T>::f1) * = 0) { T1<T>::f1(); }
void test2(double) { std::cout << "not template" << std::endl; }

//

class Test3{
public:
	template<class T> void test3(T v, decltype(f0(std::declval<T>())) * = 0) { f0(v); }
	void test3(double) { std::cout << "not template" << std::endl; }
};

class Test4{
public:
	template<class T> void test4(T, decltype(T1<T>::f1) * = 0) { T1<T>::f1(); }
	void test4(double) { std::cout << "not template" << std::endl; }
};

//

class Test5{
public:
	template<class T> Test5(T v, decltype(f0(std::declval<T>())) * = 0) { f0(v); }
	Test5(double) { std::cout << "not template" << std::endl; }
};

class Test6{
public:
	// fatal error C1001
	//template<class T> Test6(T, decltype(T1<T>::f1) * = 0) { T1<T>::f1(); }
	Test6(double) { std::cout << "not template" << std::endl; }
};

//

class Test7{
public:
	template<class T> Test7(T, typename T1<T>::Flag * = 0) { T1<T>::f1(); }
	Test7(double) { std::cout << "not template" << std::endl; }
};

//

class Test8{
public:
	template<class T> Test8(T v, std::enable_if_t<ExistF0<T>::value> * = 0) { f0(v); }
	Test8(double) { std::cout << "not template" << std::endl; }
};

class Test9{
public:
	template<class T> Test9(T, std::enable_if_t<HasF1<T>::value> * = 0) { T1<T>::f1(); }
	Test9(double) { std::cout << "not template" << std::endl; }
};


int main() {
	std::cout << "\n[test1]" << std::endl;
	test1(C1());
	test1(1);

	std::cout << "\n[test2]" << std::endl;
	test2(C1());
	test2(1);

	std::cout << "\n[Test3::test3]" << std::endl;
	Test3 c3;
	c3.test3(C1());
	c3.test3(1);

	std::cout << "\n[Test4::test4]" << std::endl;
	Test4 c4;
	c4.test4(C1());
	c4.test4(1);

	std::cout << "\n[Test5::Test5]" << std::endl;
	Test5 c5_1{ C1() };
	Test5 c5_2{ 1 };

	std::cout << "\n[Test6::Test6]" << std::endl;
	//Test6 c6_1{ C1() };
	Test6 c6_2{ 1 };

	std::cout << "\n[Test7::Test7]" << std::endl;
	Test7 c7_1{ C1() };
	Test7 c7_2{ 1 };

	std::cout << "\n[Test8::Test8]" << std::endl;
	Test8 c8_1{C1()};
	Test8 c8_2{ 1 };

	std::cout << "\n[Test9::Test9]" << std::endl;
	Test9 c9_1{ C1() };
	Test9 c9_2{ 1 };

	return 0;
}
```