1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Visual Studio でのSFINAE

Last updated at Posted at 2015-06-09

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

Test6のみfatal errorを吐く

#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;
}
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?