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;
}