2014-11-12 09:43:45 +08:00
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
2016-12-23 09:30:39 +08:00
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1z
2009-11-12 07:06:43 +08:00
// Template argument deduction with template template parameters.
template < typename T , template < T > class A >
struct X0 {
static const unsigned value = 0 ;
} ;
template < template < int > class A >
struct X0 < int , A > {
static const unsigned value = 1 ;
} ;
template < int > struct X0i ;
template < long > struct X0l ;
int array_x0a [ X0 < long , X0l > : : value = = 0 ? 1 : - 1 ] ;
int array_x0b [ X0 < int , X0i > : : value = = 1 ? 1 : - 1 ] ;
template < typename T , typename U >
struct is_same {
static const bool value = false ;
} ;
template < typename T >
struct is_same < T , T > {
static const bool value = true ;
} ;
template < typename T > struct allocator { } ;
template < typename T , typename Alloc = allocator < T > > struct vector { } ;
// Fun with meta-lambdas!
struct _1 { } ;
struct _2 { } ;
// Replaces all occurrences of _1 with Arg1 and _2 with Arg2 in T.
template < typename T , typename Arg1 , typename Arg2 >
struct Replace {
typedef T type ;
} ;
// Replacement of the whole type.
template < typename Arg1 , typename Arg2 >
struct Replace < _1 , Arg1 , Arg2 > {
typedef Arg1 type ;
} ;
template < typename Arg1 , typename Arg2 >
struct Replace < _2 , Arg1 , Arg2 > {
typedef Arg2 type ;
} ;
// Replacement through cv-qualifiers
template < typename T , typename Arg1 , typename Arg2 >
struct Replace < const T , Arg1 , Arg2 > {
typedef typename Replace < T , Arg1 , Arg2 > : : type const type ;
} ;
// Replacement of templates
template < template < typename > class TT , typename T1 , typename Arg1 , typename Arg2 >
struct Replace < TT < T1 > , Arg1 , Arg2 > {
typedef TT < typename Replace < T1 , Arg1 , Arg2 > : : type > type ;
} ;
template < template < typename , typename > class TT , typename T1 , typename T2 ,
typename Arg1 , typename Arg2 >
struct Replace < TT < T1 , T2 > , Arg1 , Arg2 > {
typedef TT < typename Replace < T1 , Arg1 , Arg2 > : : type ,
typename Replace < T2 , Arg1 , Arg2 > : : type > type ;
} ;
// Just for kicks...
template < template < typename , typename > class TT , typename T1 ,
typename Arg1 , typename Arg2 >
struct Replace < TT < T1 , _2 > , Arg1 , Arg2 > {
typedef TT < typename Replace < T1 , Arg1 , Arg2 > : : type , Arg2 > type ;
} ;
int array0 [ is_same < Replace < _1 , int , float > : : type , int > : : value ? 1 : - 1 ] ;
int array1 [ is_same < Replace < const _1 , int , float > : : type , const int > : : value ? 1 : - 1 ] ;
int array2 [ is_same < Replace < vector < _1 > , int , float > : : type , vector < int > > : : value ? 1 : - 1 ] ;
int array3 [ is_same < Replace < vector < const _1 > , int , float > : : type , vector < const int > > : : value ? 1 : - 1 ] ;
int array4 [ is_same < Replace < vector < int , _2 > , double , float > : : type , vector < int , float > > : : value ? 1 : - 1 ] ;
2009-12-30 12:10:01 +08:00
// PR5911
template < typename T , int N > void f ( const T ( & a ) [ N ] ) ;
int iarr [ ] = { 1 } ;
void test_PR5911 ( ) { f ( iarr ) ; }
2010-02-08 05:33:28 +08:00
// Must not examine base classes of incomplete type during template argument
// deduction.
namespace PR6257 {
template < typename T > struct X {
template < typename U > X ( const X < U > & u ) ;
} ;
struct A ;
void f ( A & a ) ;
void f ( const X < A > & a ) ;
void test ( A & a ) { ( void ) f ( a ) ; }
}
2010-07-13 16:18:22 +08:00
// PR7463
namespace PR7463 {
2010-07-14 14:36:18 +08:00
const int f ( ) ;
2010-07-13 16:18:22 +08:00
template < typename T_ > void g ( T_ & ) ; // expected-note{{T_ = int}}
void h ( void ) { g ( f ( ) ) ; } // expected-error{{no matching function for call}}
}
2010-08-05 17:05:08 +08:00
namespace test0 {
2015-08-15 23:23:14 +08:00
template < class T > void make ( const T * ( * fn ) ( ) ) ; // expected-note {{candidate template ignored: cannot deduce a type for 'T' that would make 'const T' equal 'char'}}
2010-08-05 17:05:08 +08:00
char * char_maker ( ) ;
void test ( ) {
make ( char_maker ) ; // expected-error {{no matching function for call to 'make'}}
}
}
2010-08-19 08:20:19 +08:00
namespace test1 {
template < typename T > void foo ( const T a [ 3 ] [ 3 ] ) ;
void test ( ) {
int a [ 3 ] [ 3 ] ;
foo ( a ) ;
}
}
2010-08-29 06:14:41 +08:00
// PR7708
namespace test2 {
template < typename T > struct Const { typedef void const type ; } ;
template < typename T > void f ( T , typename Const < T > : : type * ) ;
template < typename T > void f ( T , void const * ) ;
void test ( ) {
void * p = 0 ;
f ( 0 , p ) ;
}
}
2010-10-13 03:40:14 +08:00
// rdar://problem/8537391
namespace test3 {
struct Foo {
template < void F ( char ) > static inline void foo ( ) ;
} ;
class Bar {
template < typename T > static inline void wobble ( T ch ) ;
public :
static void madness ( ) {
Foo : : foo < wobble < char > > ( ) ;
}
} ;
}
2011-07-15 15:47:58 +08:00
// Verify that we can deduce enum-typed arguments correctly.
namespace test14 {
enum E { E0 , E1 } ;
template < E > struct A { } ;
template < E e > void foo ( const A < e > & a ) { }
void test ( ) {
A < E0 > a ;
foo ( a ) ;
}
}
2014-11-12 09:43:45 +08:00
namespace PR21536 {
template < typename . . . T > struct X ;
template < typename A , typename . . . B > struct S {
static_assert ( sizeof . . . ( B ) = = 1 , " " ) ;
void f ( ) {
using T = A ;
using T = int ;
using U = X < B . . . > ;
using U = X < int > ;
}
} ;
template < typename . . . T > void f ( S < T . . . > ) ;
void g ( ) { f ( S < int , int > ( ) ) ; }
}
2014-11-13 07:38:38 +08:00
namespace PR19372 {
template < template < typename . . . > class C , typename . . . Us > struct BindBack {
template < typename . . . Ts > using apply = C < Ts . . . , Us . . . > ;
} ;
template < typename , typename . . . > struct Y ;
template < typename . . . Ts > using Z = Y < Ts . . . > ;
using T = BindBack < Z , int > : : apply < > ;
using T = Z < int > ;
using U = BindBack < Z , int , int > : : apply < char > ;
using U = Z < char , int , int > ;
2014-11-13 07:43:08 +08:00
namespace BetterReduction {
template < typename . . . > struct S ;
2014-11-13 07:50:13 +08:00
template < typename . . . A > using X = S < A . . . > ; // expected-note {{parameter}}
2014-11-13 07:43:08 +08:00
template < typename . . . A > using Y = X < A . . . , A . . . > ;
2014-11-13 07:50:13 +08:00
template < typename . . . A > using Z = X < A . . . , 1 , 2 , 3 > ; // expected-error {{must be a type}}
2014-11-13 07:43:08 +08:00
using T = Y < int > ;
using T = S < int , int > ;
}
2014-11-13 07:38:38 +08:00
}
2015-01-16 23:20:14 +08:00
namespace PR18645 {
template < typename F > F Quux ( F & & f ) ;
auto Baz = Quux ( Quux < float > ) ;
}
2015-12-31 04:56:05 +08:00
namespace NonDeducedNestedNameSpecifier {
template < typename T > struct A {
template < typename U > struct B {
B ( int ) { }
} ;
} ;
template < typename T > int f ( A < T > , typename A < T > : : template B < T > ) ;
int k = f ( A < int > ( ) , 0 ) ;
}
2016-05-19 10:28:21 +08:00
namespace PR27601_RecursivelyInheritedBaseSpecializationsDeductionAmbiguity {
namespace ns1 {
template < class . . . > struct B { } ;
template < class H , class . . . Ts > struct B < H , Ts . . . > : B < > { } ;
template < class . . . Ts > struct D : B < Ts . . . > { } ;
template < class T , class . . . Ts > void f ( B < T , Ts . . . > & ) { }
int main ( ) {
D < int , char > d ;
f < int > ( d ) ;
}
} //end ns1
namespace ns2 {
template < int i , typename . . . Es > struct tup_impl ;
template < int i > struct tup_impl < i > { } ; // empty tail
template < int i , typename Head , typename . . . Tail >
struct tup_impl < i , Head , Tail . . . > : tup_impl < i + 1 , Tail . . . > {
using value_type = Head ;
Head head ;
} ;
template < typename . . . Es > struct tup : tup_impl < 0 , Es . . . > { } ;
template < typename Head , int i , typename . . . Tail >
Head & get_helper ( tup_impl < i , Head , Tail . . . > & t ) {
return t . head ;
}
template < typename Head , int i , typename . . . Tail >
Head const & get_helper ( tup_impl < i , Head , Tail . . . > const & t ) {
return t . head ;
}
int main ( ) {
tup < int , double , char > t ;
get_helper < double > ( t ) ;
return 0 ;
}
} // end ns2
2016-09-29 06:08:38 +08:00
}
2016-12-23 09:30:39 +08:00
namespace multiple_deduction_different_type {
template < typename T , T v > struct X { } ;
template < template < typename T , T > class X , typename T , typename U , int N >
void f ( X < T , N > , X < U , N > ) { } // expected-note 2{{values of conflicting types}}
template < template < typename T , T > class X , typename T , typename U , const int * N >
void g ( X < T , N > , X < U , N > ) { } // expected-note 0-2{{values of conflicting types}}
int n ;
void h ( ) {
f ( X < int , 1 + 1 > ( ) , X < unsigned int , 3 - 1 > ( ) ) ; // expected-error {{no matching function}}
f ( X < unsigned int , 1 + 1 > ( ) , X < int , 3 - 1 > ( ) ) ; // expected-error {{no matching function}}
# if __cplusplus > 201402L
g ( X < const int * , & n > ( ) , X < int * , & n + 1 - 1 > ( ) ) ; // expected-error {{no matching function}}
g ( X < int * , & n > ( ) , X < const int * , & n + 1 - 1 > ( ) ) ; // expected-error {{no matching function}}
# endif
}
template < template < typename T , T > class X , typename T , typename U , T N >
void x ( X < T , N > , int ( * ) [ N ] , X < U , N > ) { } // expected-note 1+{{candidate}}
template < template < typename T , T > class X , typename T , typename U , T N >
void x ( int ( * ) [ N ] , X < T , N > , X < U , N > ) { } // expected-note 1+{{candidate}}
int arr [ 3 ] ;
void y ( ) {
x ( X < int , 3 > ( ) , & arr , X < int , 3 > ( ) ) ;
x ( & arr , X < int , 3 > ( ) , X < int , 3 > ( ) ) ;
x ( X < int , 3 > ( ) , & arr , X < char , 3 > ( ) ) ; // expected-error {{no matching function}}
x ( & arr , X < int , 3 > ( ) , X < char , 3 > ( ) ) ; // expected-error {{no matching function}}
x ( X < char , 3 > ( ) , & arr , X < char , 3 > ( ) ) ;
x ( & arr , X < char , 3 > ( ) , X < char , 3 > ( ) ) ;
}
}
2016-09-29 06:08:38 +08:00
namespace nullptr_deduction {
2016-12-23 09:30:39 +08:00
using nullptr_t = decltype ( nullptr ) ;
2016-09-29 06:08:38 +08:00
template < typename T , T v > struct X { } ;
template < typename T , T v > void f ( X < T , v > ) {
static_assert ( ! v , " " ) ;
}
2016-12-23 09:30:39 +08:00
void g ( ) {
f ( X < int * , nullptr > ( ) ) ;
f ( X < nullptr_t , nullptr > ( ) ) ;
}
template < template < typename T , T > class X , typename T , typename U , int * P >
void f1 ( X < T , P > , X < U , P > ) { } // expected-note 2{{values of conflicting types}}
void h ( ) {
f1 ( X < int * , nullptr > ( ) , X < nullptr_t , nullptr > ( ) ) ; // expected-error {{no matching function}}
f1 ( X < nullptr_t , nullptr > ( ) , X < int * , nullptr > ( ) ) ; // expected-error {{no matching function}}
}
template < template < typename T , T > class X , typename T , typename U , nullptr_t P >
void f2 ( X < T , P > , X < U , P > ) { } // expected-note 2{{values of conflicting types}}
void i ( ) {
f2 ( X < int * , nullptr > ( ) , X < nullptr_t , nullptr > ( ) ) ; // expected-error {{no matching function}}
f2 ( X < nullptr_t , nullptr > ( ) , X < int * , nullptr > ( ) ) ; // expected-error {{no matching function}}
}
}
namespace member_pointer {
struct A { void f ( int ) ; } ;
template < typename T , void ( A : : * F ) ( T ) > struct B ;
template < typename T > struct C ;
template < typename T , void ( A : : * F ) ( T ) > struct C < B < T , F > > {
C ( ) { A a ; T t ; ( a . * F ) ( t ) ; }
} ;
C < B < int , & A : : f > > c ;
2016-09-29 06:08:38 +08:00
}
2016-12-24 12:09:05 +08:00
namespace deduction_substitution_failure {
2016-12-24 12:20:31 +08:00
template < typename T > struct Fail { typedef typename T : : error error ; } ; // expected-error 2{{prior to '::'}}
2016-12-24 12:09:05 +08:00
template < typename T , typename U > struct A { } ;
template < typename T > struct A < T , typename Fail < T > : : error > { } ; // expected-note {{instantiation of}}
A < int , int > ai ; // expected-note {{during template argument deduction for class template partial specialization 'A<T, typename Fail<T>::error>' [with T = int]}}
template < typename T , typename U > int B ; // expected-warning 0-1 {{extension}}
2016-12-24 12:20:31 +08:00
template < typename T > int B < T , typename Fail < T > : : error > { } ; // expected-note {{instantiation of}}
int bi = B < char , char > ; // expected-note {{during template argument deduction for variable template partial specialization 'B<T, typename Fail<T>::error>' [with T = char]}}
2016-12-24 12:09:05 +08:00
}
2017-01-03 07:00:32 +08:00
namespace deduction_after_explicit_pack {
template < typename . . . T , typename U > int * f ( T . . . t , int & r , U * u ) { // expected-note {{couldn't infer template argument 'U'}}
return u ;
}
template < typename U , typename . . . T > int * g ( T . . . t , int & r , U * u ) {
return u ;
}
void h ( float a , double b , int c ) {
// FIXME: Under DR1388, this appears to be valid.
f < float & , double & > ( a , b , c , & c ) ; // expected-error {{no matching}}
g < int , float & , double & > ( a , b , c , & c ) ; // ok
}
}