45用d编程元组
元组Tuple
,是std.typecons
实现的库特征
.合并多个值进一个值.
利用std.meta
的AliasSeq
来完成某些操作.
更多可见此
import std.stdio;
import std.typecons;
void main() {
auto t = tuple(42, "hello");//可用tuple构建
writeln(t);//Tuple!(int, string)(42, "hello")
}
等价于:
//等价Tuple!(int, string)
struct __Tuple_int_string {
int __member_0;
string __member_1;
}
//这样访问
writeln(t[0]);
writeln(t[1]);
还可以这样:
auto t = Tuple!(int, "number",string, "message")(42, "hello");
//相当于别名,或者说一个结构的成员的名字,两个两个的
writeln("by index 0 : ", t[0]);
writeln("by .number : ", t.number);
writeln("by index 1 : ", t[1]);
writeln("by .message: ", t.message);
//相当于定义了一个结构了.
元组可变为值列表,这样就可以直接传入参数
了.
import std.stdio;
import std.typecons;
void foo(int i, string s, double d, char c) {
// ...
}
void bar(int i, double d, char c) {
// ...
}
void main() {
auto t = tuple(1, "2", 3.3, '4');
// foo(1, "2", 3.3, '4'):
foo(t.expand);//可扩展一下,就进去了.
foo(t[]);//等价于上面的形式
bar(t[0],t[$-2..$]);//等价于bar(1, 3.3, '4')
}
还可以这样:
import std.stdio;
import std.typecons;
void main() {
auto t = tuple(1, 2, 3);
auto a = [ t.expand, t[] ];//扩展,应是值类型
//要求类型匹配.这样a就相当于字面量了.
writeln(a);
}
编译时foreach
auto t = tuple(42, "hello", 1.5);
foreach (i, member; t) {//编译时
writefln("%s: %s", i, member);
}
看起来像运行时,实际上不是,实质是:
{
enum size_t i = 0;
int member = t[i];
writefln("%s: %s", i, member);
}
{
enum size_t i = 1;
string member = t[i];
writefln("%s: %s", i, member);
}
{
enum size_t i = 2;
double member = t[i];
writefln("%s: %s", i, member);
}
每一
对元组执行展开
操作.主要是元组类型
不同,所以都得展开.
同时,可以一次返回一个元组,如std.algorithm.findSplit
import std.algorithm;
// ...
auto entireRange = "hello";
auto searched = "ll";
auto result=findSplit(entireRange, searched);
writeln("before: ", result[0]);
writeln("found : ", result[1]);
writeln("after : ", result[2]);
或者是返回结构:
struct Result {
// ...
}
Result foo() {
// ...
}
std.meta
中定义的AliasSeq
.表示的是编译器
常用,而编程作为实体不可用的概念.如,
分隔的值,类型,符号(如 别名模板参数)
.3个例子:函数参数列表,模板参数列表,数组字面量元素列表
foo(1, "hello", 2.5);
auto o = Bar!(char, long)();
auto a = [ 1, 2, 3, 4 ];
元组扩展成员时利用它.AliasSeq包含类型,值,符号
.
AliasSeq 和 std.meta,过去为TypeTuple 和 std.typetuple
本章包含仅值和仅类型
.在可变模板
中特别有用.
import std.stdio;
void foo(int i, string s, double d) {
writefln("用%s, %s, 和 %s调用foo.", i, s, d);
}
限定AliasSeq
的值为模板参数.包含值/类型
一般这样调用foo(1, "hello", 2.5);
,
现在可以这样:
import std.meta;
// ...
alias arguments = AliasSeq!(1, "hello", 2.5);
foo(arguments);
将参数打包为一个别名序列了.
arguments,是AliasSeq
模板的一个实例的别名.
还可用AliasSeq
来实例化数组.即就是一个序列.
alias elements = AliasSeq!(1, 2, 3, 4);
auto arr = [ elements ];//但要元素类型匹配
assert(arr == [ 1, 2, 3, 4 ]);
索引与切片.
alias arguments = AliasSeq!(1, "hello", 2.5);
assert(arguments[0] == 1);
assert(arguments[1] == "hello");
assert(arguments[2] == 2.5);//就是一个序列
还可以像这样:
void bar(string s, double d) {
// ...
}
// ...
bar(arguments[$-2 .. $]);//最后两位参数匹配
包含类型列表
,即(整,双精…)
import std.conv;
struct S(ElementT, ResultT) {//元素类型,返回类型
ElementT[] arr;
ResultT length() {
return to!ResultT(arr.length);
}
}
void main() {
auto s = S!(double, int)([ 1, 2, 3 ]);
auto l = s.length();
}
看看
import std.meta;
// ...
alias Types = AliasSeq!(double, int);
auto s = S!Types([ 1, 2, 3 ]);//现在别名为类型序列了
看起来像单个参数,使用时自动扩展了,在可变模板
中很有用.
AliasSeq
还可与foreach
搭配.而且是在编译时,为每个成员展开.
unittest {
alias Types = AliasSeq!(int, long, float);
foreach (Type; Types) {
auto s = S!(Type, size_t)([ Type.init, Type.init ]);
assert(s.length() == 2);
}
}
//变成这样
{
auto s = S!(int, size_t)([ int.init, int.init ]);
assert(s.length() == 2);
}
{//整,长,浮,展开
auto s = S!(long, size_t)([ long.init, long.init ]);
assert(s.length() == 2);
}
{
auto s = S!(float, size_t)([ float.init, float.init ]);
assert(s.length() == 2);
}
.tupleof
属性.展示类型/对象
的成员
.对自定义类型
,可访问类型成员的定义.
import std.stdio;
struct S {
int number;
string message;
double value;
}
void main() {
foreach (i, MemberType; typeof(S.tupleof)){
writefln("Member %s:", i);
writefln("type: %s", MemberType.stringof);
string name = S.tupleof[i].stringof;
writefln(" name: %s", name);
}//对类型的每一.
}
第一个应用.tupleof
的typeof
,来取元素们的类型
他们的名字由S.tupleof[i].stringof
来取
tupleof
取的是值.也可作用于对象
.
auto object = S(42, "hello", 1.5);
foreach (i, member; object.tupleof) {
writefln("成员 %s:", i);
writefln("类型 : %s", typeof(member).stringof);
writefln("值: %s", member);
}
有两套系统值和类型系统
.要注意,元组
是对象
自身成员的引用,不是副本.
元组合并多个值就像一个结构一样,一般为临时少量使用.没有名字.
显式使用时,允许按属性
访问成员.
可用.扩展
或切片扩展
每一元组不是运行时循环,而是编译时展开
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现