delete-and-function-templates.cpp
4.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only -emit-llvm-only %s
// RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only -fdelayed-template-parsing %s
// RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only -fms-extensions %s
// RUN: %clang_cc1 -std=c++11 -verify -fsyntax-only -fdelayed-template-parsing -fms-extensions %s
template<class T, class U> struct is_same { enum { value = false }; };
template<class T> struct is_same<T, T> { enum { value = true }; };
namespace test_sfinae_and_delete {
namespace ns1 {
template<class T> double f(T) = delete; //expected-note{{candidate}}
char f(...); //expected-note{{candidate}}
static_assert(is_same<decltype(f(3)),char>::value, ""); //expected-error{{call to deleted function}} expected-error{{static_assert failed}}
template<class T> decltype(f(T{})) g(T); // this one sfinae's out.
template<class T> int *g(T);
void foo() {
int *ip = g(3);
}
} //end ns1
namespace ns2 {
template<class T> double* f(T);
template<> double* f(double) = delete;
template<class T> decltype(f(T{})) g(T); // expected-note{{candidate}}
template<class T> int *g(T); //expected-note{{candidate}}
void foo() {
double *dp = g(3); //expected-error{{ambiguous}}
int *ip = g(3.14); // this is OK - because the explicit specialization is deleted and sfinae's out one of the template candidates
}
} // end ns2
namespace ns3 {
template<class T> double* f(T) = delete;
template<> double* f(double);
template<class T> decltype(f(T{})) g(T); // expected-note{{candidate}}
template<class T> int *g(T); //expected-note{{candidate}}
void foo() {
int *dp = g(3); // this is OK - because the non-double specializations are deleted and sfinae's out one of the template candidates
double *ip = g(3.14); //expected-error{{ambiguous}}
}
} // end ns3
} // end ns test_sfinae_and_delete
namespace test_explicit_specialization_of_member {
namespace ns1 {
template<class T> struct X {
int* f(T) = delete;
};
template<> int* X<int>::f(int) { }
template<class T> decltype(X<T>{}.f(T{})) g(T); // expected-note{{candidate}}
template<class T> int *g(T); //expected-note{{candidate}}
void foo() {
int *ip2 = g(3.14); // this is OK - because the non-int specializations are deleted and sfinae's out one of the template candidates
int *ip = g(3); //expected-error{{ambiguous}}
}
} // end ns1
namespace ns2 {
struct X {
template<class T> double* f(T) = delete;
};
template<> double* X::f(int);
template<class T> decltype(X{}.f(T{})) g(T); // expected-note{{candidate}}
template<class T> int *g(T); //expected-note{{candidate}}
void foo() {
int *ip2 = g(3.14); // this is OK - because the non-int specializations are deleted and sfinae's out one of the template candidates
int *ip = g(3); //expected-error{{ambiguous}}
}
} // end ns2
namespace ns3 {
template<class T> struct X {
template<class U> double *f1(U, T) = delete;
template<class U> double *f2(U, T) = delete;
};
template<> template<> double* X<int>::f1(int, int);
template<> template<class U> double* X<int>::f2(U, int);
template<class T, class U> decltype(X<T>{}.f1(U{}, T{})) g1(U, T); // expected-note{{candidate}}
template<class T, class U> int *g1(U, T); //expected-note{{candidate}}
template<class T, class U> decltype(X<T>{}.f2(U{}, T{})) g2(U, T); // expected-note2{{candidate}}
template<class T, class U> int *g2(U, T); //expected-note2{{candidate}}
void foo() {
int *ip2 = g1(3.14, 3); // this is OK - because the non-int specializations are deleted and sfinae's out one of the template candidates
int *ip = g1(3, 3); //expected-error{{ambiguous}}
{
int *ip3 = g2(3.14, 3); //expected-error{{ambiguous}}
int *ip4 = g2(3, 3); //expected-error{{ambiguous}}
}
{
int *ip3 = g2(3.14, 3.14);
int *ip4 = g2(3, 3.14);
}
}
} // end ns3
namespace ns4 {
template < typename T> T* foo (T);
template <> int* foo(int) = delete;
template <> int* foo(int); //expected-note{{candidate}}
int *IP = foo(2); //expected-error{{deleted}}
double *DP = foo(3.14);
} //end ns4
namespace ns5 {
template < typename T> T* foo (T);
template <> int* foo(int); //expected-note{{previous}}
template <> int* foo(int) = delete; //expected-error{{deleted definition must be first declaration}}
} //end ns5
} // end test_explicit_specializations_and_delete