模板
来源:互联网 发布:网络安全工程师面试题 编辑:程序博客网 时间:2024/04/28 19:26
// Scoped Template
template Foo(T, U)
{
class Bar {} // 类
T foo(T t, U u) { return t; } // 函数
T abc; // 变量
alias T* TPtr; // 类型别名
}
alias Foo!(int, char) TFoo;
void demo1()
{
TFoo.Bar b; // 自动初始化为null
TFoo.foo(1, 'a');
TFoo.abc = 3;
TFoo.TPtr p; // 自动初始化为0x00
auto i = 0;
}
// 类模板
class Abc(T)
{
T _t;
}
alias Abc!(int) TAbc;
void demo2()
{
TAbc abc; // 自动初始化为null
auto i = 1;
}
// 多个模块中的模板
//module a;
//
//template Foo(T)
//{
// T bar;
//}
//
//module b;
//
//import std.stdio;
//import a;
//
//void test()
//{
// a.Foo!(int).bar = 3;
// writeln("module b");
//}
//
//module c;
//
//import std.stdio;
//import a;
//
//alias a.Foo!(int).bar bar;
//
//void test()
//{
// bar = 3;
// writeln("module c");
//}
//
//module main;
//
//import std.stdio;
//import b, c;
//
//void main()
//{
// b.test();
// c.test();
//
// getchar();
//}
class D
{
}
class C : D
{
}
interface I
{
}
class U : I
{
}
// 复杂的模板参数
class Foo( // 注意这个类模板与前面的Foo模板同名!!
R, // R 可以是任何类型
P: P*, // P 必须是指针类型
T: int, // T 必须是 int 类型,即这个参数只能是int
S: T*, // S 必须是指向 T 的指针,即这个参数只能是int*
C: D, // C 必须属于类 D 或者是派生自 D
U: I, // U 必须是这样一个类:实现了接口 I 的类
f: float, // f必须是float类型
float data, // 该参数要求是一个float类型的变量
string str = "hello", // 该参数要求是一个字符串,默认值为 "hello"。注意有默认值的参数不能放中间
alias A = D // A 是任何符号(包括模板符号),默认是 D。注意有默认值的参数不能放中间
)
{
void print()
{
writeln("in class template");
}
}
void demo3()
{
int a = 5;
alias Foo!(D, byte*, int, int*, C, U, float, 1) TFoo;
TFoo f = new TFoo();
f.print();
}
int g(double d)
{
return 1;
}
alias double A; // 全局的
class B(T)
{
alias int A; // 模板内部的
}
// 类模板的继承
class X(T) : B!(T)
{
A a; // a 的类型是 int
int T; // 正确,T 被重新声明为 int
int foo()
{
char T; // 正确,T 被重新声明为 char
return g(1); // 总是返回 2,调用的是后面那个精确匹配的函数
}
};
void demo4()
{
alias X!(int) TX;
auto x = new TX();
auto i = x.foo();
}
// 函数可以被向前引用
int g(int i)
{
return 2;
}
// 模板实现递归
// 方法1
template factorial(int n)
{
const factorial = n * factorial!(n - 1); // const是什么意思,为什么变量名必须与模板名相同才可以编译过?
}
template factorial(int n : 1) // 模板特化
{
const factorial = 1;
}
// 方法2
template factorial0(int n)
{
static if (n == 1) // static if?
{
const factorial0 = 1;
}
else
{
const factorial0 = n * factorial0!(n - 1);
}
}
void demo5()
{
writeln(factorial!(4)); // 输出 24
writeln(factorial0!(4)); // 输出 24
}
template hash(string s, uint sofar = 0)
{
static if (0 == s.length)
{
const hash = sofar;
}
else
{
const hash = hash!(s[1 .. $], sofar * 11 + s[0]);
}
}
uint demo6()
{
return hash!("i lovd lulu");
}
template decimalDigit(int n) // [3]
{
const string decimalDigit = "0123456789"[n .. n + 1];
}
template itoa(long n)
{
static if (n < 0)
{
const string itoa = "-" ~ itoa!(-n);
}
else static if (n < 10)
{
const string itoa = decimalDigit!(n);
}
else
{
const string itoa = itoa!(n / 10L) ~ decimalDigit!(n % 10L);
}
}
string demo7()
{
return itoa!(264); // 返回 "264"
}
template Foo(T, U)
{
class Bar {} // 类
T foo(T t, U u) { return t; } // 函数
T abc; // 变量
alias T* TPtr; // 类型别名
}
alias Foo!(int, char) TFoo;
void demo1()
{
TFoo.Bar b; // 自动初始化为null
TFoo.foo(1, 'a');
TFoo.abc = 3;
TFoo.TPtr p; // 自动初始化为0x00
auto i = 0;
}
// 类模板
class Abc(T)
{
T _t;
}
alias Abc!(int) TAbc;
void demo2()
{
TAbc abc; // 自动初始化为null
auto i = 1;
}
// 多个模块中的模板
//module a;
//
//template Foo(T)
//{
// T bar;
//}
//
//module b;
//
//import std.stdio;
//import a;
//
//void test()
//{
// a.Foo!(int).bar = 3;
// writeln("module b");
//}
//
//module c;
//
//import std.stdio;
//import a;
//
//alias a.Foo!(int).bar bar;
//
//void test()
//{
// bar = 3;
// writeln("module c");
//}
//
//module main;
//
//import std.stdio;
//import b, c;
//
//void main()
//{
// b.test();
// c.test();
//
// getchar();
//}
class D
{
}
class C : D
{
}
interface I
{
}
class U : I
{
}
// 复杂的模板参数
class Foo( // 注意这个类模板与前面的Foo模板同名!!
R, // R 可以是任何类型
P: P*, // P 必须是指针类型
T: int, // T 必须是 int 类型,即这个参数只能是int
S: T*, // S 必须是指向 T 的指针,即这个参数只能是int*
C: D, // C 必须属于类 D 或者是派生自 D
U: I, // U 必须是这样一个类:实现了接口 I 的类
f: float, // f必须是float类型
float data, // 该参数要求是一个float类型的变量
string str = "hello", // 该参数要求是一个字符串,默认值为 "hello"。注意有默认值的参数不能放中间
alias A = D // A 是任何符号(包括模板符号),默认是 D。注意有默认值的参数不能放中间
)
{
void print()
{
writeln("in class template");
}
}
void demo3()
{
int a = 5;
alias Foo!(D, byte*, int, int*, C, U, float, 1) TFoo;
TFoo f = new TFoo();
f.print();
}
int g(double d)
{
return 1;
}
alias double A; // 全局的
class B(T)
{
alias int A; // 模板内部的
}
// 类模板的继承
class X(T) : B!(T)
{
A a; // a 的类型是 int
int T; // 正确,T 被重新声明为 int
int foo()
{
char T; // 正确,T 被重新声明为 char
return g(1); // 总是返回 2,调用的是后面那个精确匹配的函数
}
};
void demo4()
{
alias X!(int) TX;
auto x = new TX();
auto i = x.foo();
}
// 函数可以被向前引用
int g(int i)
{
return 2;
}
// 模板实现递归
// 方法1
template factorial(int n)
{
const factorial = n * factorial!(n - 1); // const是什么意思,为什么变量名必须与模板名相同才可以编译过?
}
template factorial(int n : 1) // 模板特化
{
const factorial = 1;
}
// 方法2
template factorial0(int n)
{
static if (n == 1) // static if?
{
const factorial0 = 1;
}
else
{
const factorial0 = n * factorial0!(n - 1);
}
}
void demo5()
{
writeln(factorial!(4)); // 输出 24
writeln(factorial0!(4)); // 输出 24
}
template hash(string s, uint sofar = 0)
{
static if (0 == s.length)
{
const hash = sofar;
}
else
{
const hash = hash!(s[1 .. $], sofar * 11 + s[0]);
}
}
uint demo6()
{
return hash!("i lovd lulu");
}
template decimalDigit(int n) // [3]
{
const string decimalDigit = "0123456789"[n .. n + 1];
}
template itoa(long n)
{
static if (n < 0)
{
const string itoa = "-" ~ itoa!(-n);
}
else static if (n < 10)
{
const string itoa = decimalDigit!(n);
}
else
{
const string itoa = itoa!(n / 10L) ~ decimalDigit!(n % 10L);
}
}
string demo7()
{
return itoa!(264); // 返回 "264"
}