template < - >
|
|||||||||
- :
- , ;
- ;
- .
,
| () | (1) | ||||||||
() = default
|
(2) | ||||||||
... ()
|
(3) | ( C++11) | |||||||
| (4) | ( C++17) | ||||||||
, , , ( cv-, ):
- lvalue ( );
- ;
- ( );
- ( - -);
- ;
| ( C++11) |
|
( C++20) |
, .
, , , prvalue, lvalue, ( C++20).
class Foo Foo, class Foo class Foo x; x Foo.
|
, - ( template<auto n>
struct B { /* ... */ };
B<5> b1; // OK: int
B<'a'> b2; // OK: char
B<2.5> b3; // ( ++20): double
// ++20 ,
//
template<std::array arr>
void f();
f<std::array<double, 8>{}>();
, -, : template<auto...>
struct C {};
C<'C', 0, 2L, nullptr> x; // OK
|
( C++17) |
struct A
{
friend bool operator==(const A&, const A&) = default;
};
template<A a>
void f()
{
&a; // OK
const A& ra = a, &rb = a; //
assert(&ra == &rb); //
}
|
( C++20) |
| -- () | (1) | ||||||||
-- () = default
|
(2) | ||||||||
-- ... ()
|
(3) | ( C++11) | |||||||
| - () | (4) | ( C++20) | |||||||
- () = default
|
(5) | ( C++20) | |||||||
- ... ()
|
(6) | ( C++20) | |||||||
| -- | typename, class.
| |
| - | , , ( ). , |
template<class T>
class My_vector { /* ... */ };
template<class T = void>
struct My_op_functor { /* ... */ };
template<My_concept T>
class My_constrained_vector { /* ... */ };
template<My_concept T = void>
class My_constrained_op_functor { /* ... */ };
:
// , :
template<class>
class My_vector;
template<class = void>
struct My_op_functor;
template<typename...>
class My_tuple;
typedef-, , .
|
template<typename T>
concept C1 = true;
template<typename... Ts> //
concept C2 = true;
template<typename T, typename U>
concept C3 = true;
template<C1 T> struct s1; // - C1<T>
template<C1... T> struct s2; // - (C1<T> && ...)
template<C2... T> struct s3; // - (C2<T> && ...)
template<C3<int> T> struct s4; // - C3<T, int>
template<C3<int>... T> struct s5; // - (C3<T, int> && ...)
|
( C++20) |
template < - > -- ()
|
(1) | ||||||||
template < - > -- () = default
|
(2) | ||||||||
template < - > -- ... ()
|
(3) | ( C++11) | |||||||
| -- | class typename ( C++17)
|
( ).
template<typename T>
class my_array {};
// :
template<typename K, typename V, template<typename> typename C = my_array>
class Map
{
C<K> key;
C<V> value;
};
( ). , .
template<class T, int N>
class Y
{
int T; // :
void f()
{
char T; // :
}
};
template<class X>
class X; // :
, , , , .
template<class T>
struct A
{
struct B {};
typedef void C;
void f();
template<class U>
void g(U);
};
template<class B>
void A<B>::f()
{
B b; // B A
}
template<class B>
template<class C>
void A<B>::g(C)
{
B b; // B A
C c; // C, C A
}
, , , .
namespace N
{
class C {};
template<class T>
class B
{
void f(T);
};
}
template<class C>
void N::B<C>::f(C)
{
C b; // C , N::C
}
struct A
{
struct B {};
int C;
int Y;
};
template<class B, class C>
struct X : A
{
B b; // B A
C b; // : C A
};
(, ) . , , ( C++17) . , , .
template<class T>
void f(); // #1
template<int I>
void f(); // #2
void g()
{
f<int()>(); // "int()" , ,
// #1,
}
, :
, , , , . |
( C++17) |
template<const int* pci>
struct X {};
int ai[10];
X<ai> xi; // OK: cv-
struct Y {};
template<const Y& b>
struct Z {};
Y y;
Z<y> z; // OK:
template<int (&pa)[5]>
struct W {};
int b[5];
W<b> w; // OK:
void f(char);
void f(int);
template<void (*pf)(int)>
struct A {};
A<&f> a; // OK: f(int)
( C++20) /
template<class T, const char* p>
class X {};
X<int, "Studebaker"> x1; // :
template<int* p>
class X {};
int a[10];
struct S
{
int m;
static int s;
} s;
X<&a[2]> x3; // ( C++20):
X<&s.m> x4; // ( C++20):
X<&s.s> x5; // OK:
X<&S::s> x6; // OK:
template<const int& CRI>
struct B {};
B<1> b2; // :
int c = 1;
B<c> b1; // OK
|
( C++17) |
-, :
template<typename T>
class X {}; //
struct A; //
typedef struct {} B; //
int main()
{
X<A> x1; // OK: 'A'
X<A*> x2; // OK: 'A*'
X<B> x3; // OK: 'B'
}
-, .
, . , , , , , .
template<typename T> //
class A { int x; };
template<typename T> //
class A<T*> { long x; };
// V
template<template<typename> class V>
class C
{
V<int> y; //
V<int*> z; //
};
C<A> c; // c.y.x int, c.z.x long
A P, P , A ( ). P , ( ) A . ( C++11)
- , ,
PA. - ,
X, ,PP,AA.PP,AAPP...; , ( C++11)AA-PP.
, P , , , A.
template<typename T>
struct eval; //
template<template<typename, typename...> class TT, typename T1, typename... Rest>
struct eval<TT<T1, Rest...>> {}; // eval
template<typename T1> struct A;
template<typename T1, typename T2> struct B;
template<int N> struct C;
template<typename T1, int N> struct D;
template<typename T1, typename T2, int N = 17> struct E;
eval<A<int>> eA; // OK: eval
eval<B<int, float>> eB; // OK: eval
eval<C<17>> eC; // : C TT
// TT
// , 17
eval<D<int, 17>> eD; // : D TT
// TT
// , 17
eval<E<int, float>> eE; // : E TT ,
// E ( )
P0522R0 A P. .
(CWG#150), , , C++17 - C++17. :
- GCC C++17, , .
- Clang , , .
- Microsoft Visual Studio C++17 C++17 (.. C++14, ).
template<class T> class A { /* ... */ };
template<class T, class U = T> class B { /* ... */ };
template<class... Types> class C { /* ... */ };
template<template<class> class P> class X { /* ... */ };
X<A> xa; // OK
X<B> xb; // OK P0522R0
// :
X<C> xc; // OK P0522R0
// :
template<template<class...> class Q> class Y { /* ... */ };
Y<A> ya; // OK
Y<B> yb; // OK
Y<C> yc; // OK
template<auto n> class D { /* ... */ }; // : C++17
template<template<int> class R> class Z { /* ... */ };
Z<D> zd; // OK P0522R0:
// ,
template<int> struct SI { /* ... */ };
template<template<auto> class> void FA(); // : C++17
FA<SI>(); //
=. (, ), ( C++11).
, , ( C++14) , , , ( C++11). , , , ( C++11).
| ( C++11) |
|
, , . |
( C++11) |
, , :
template<typename T1, typename T2 = int> class A;
template<typename T1 = int, typename T2> class A;
// :
template<typename T1 = int, typename T2 = int> class A;
:
template<typename T = int> class X;
template<typename T = int> class X {}; //
, > , -:
template<int i = 3 > 4> //
class X { /* ... */ };
template<int i = (3 > 4)> // OK
class Y { /* ... */ };
, , :
//
template<typename T = float>
struct B {};
// T ,
//
template<template<typename = float> typename T>
struct A
{
void f();
void g();
};
// -
template<template<typename TT> class T>
void A<T>::f()
{
T<> t; // : TT
}
template<template<typename TT = char> class T>
void A<T>::g()
{
T<> t; // OK: t T<char>
}
class B {};
template<typename T>
class C
{
protected:
typedef T TT;
};
template<typename U, typename V = typename U::TT>
class D: public U {};
D<C<B>>* d; // : C::TT
|
, , , : template<typename T, typename U = int>
struct S {};
S<bool>* p; // U
// p S<bool, int>*
|
( C++14) |
--,
- ,
- , ,
- lvalue
|
( C++11) |
|
( C++20) |
__cpp_nontype_template_parameter_auto |
201606L |
(C++17) | , auto
|
__cpp_template_template_args |
201611L |
(c++17) | |
__cpp_nontype_template_args |
201411L |
(C++17) | |
201911L |
(C++20) | , |
#include <array>
#include <iostream>
#include <numeric>
// ,
template<int N>
struct S { int a[N]; };
template<const char*>
struct S2 {};
//
template
<
char c, //
int (&ra)[5], // lvalue ( )
int (*pf)(int), //
int (S<10>::*a)[10] // - ( int[10])
>
struct Complicated
{
// ,
// ,
void foo(char base)
{
ra[4] = pf(c - base);
}
};
// S2<"fail"> s2; // :
char okay[] = "okay"; //
// S2<&okay[0]> s3; // :
S2<okay> s4; //
int a[5];
int f(int n) { return n; }
// C++20: NTTP
template<std::array arr>
constexpr
auto sum() { return std::accumulate(arr.cbegin(), arr.cend(), 0); }
// C++20:
static_assert(sum<std::array<double, 8>{3, 1, 4, 1, 5, 9, 2, 6}>() == 31.0);
// C++20: NTTP CTAD
static_assert(sum<std::array{2, 7, 1, 8, 2, 8}>() == 28);
int main()
{
S<10> s; // s.a 10 int
s.a[9] = 4;
Complicated<'2', a, f, &S<10>::a> c;
c.foo('0');
std::cout << s.a[9] << a[4] << '\n';
}
:
42
| : |
C++:
| CWG 150 | C++98 | - - |
( P0522R0) |
| CWG 184 | C++98 | , |
|
| CWG 354 | C++98 | , |
|
| CWG 1398 | C++11 | std::nullptr_t
|
|
| CWG 1570 | C++98 | |
|
| CWG 1922 | C++98 | , , , |
|
| CWG 2032 | C++14 | |
, |