如何声明File.byLine()赋值的变量类型?结构体模板推导报错
解决D语言ThingReader结构体的成员类型声明问题
看起来你卡在了结构体成员类型的声明和模板实例化推导上,我来一步步帮你解决:
核心问题拆解
你遇到的几个问题本质是:
- D语言的结构体成员不能直接用
auto声明(除非是较新版本的D支持的特性); - 模板结构体实例化时,编译器不会自动推导模板参数;
- 直接写
ByLine报错是因为它是模板类型,需要指定参数或正确导入。
具体解决方案
方案1:用模板结构体+显式推导/工厂函数(最通用)
你的模板结构体思路是正确的,只是实例化方式不对。D的结构体不会自动推导模板参数,我们可以用两种方式解决:
方法A:显式指定模板参数
实例化时,用typeof(f.byLine)获取byLine返回的实际类型:
// 你的模板结构体保持不变 struct ThingReader(Lines) { Lines lines; Thing thing; this(File f) { this.lines = f.byLine; popFront; } @property bool empty() { return lines.empty; } @property ref Thing front() { return thing; } void popFront() { if (!empty) { auto l = lines.front; lines.popFront; parseLine(l, thing); // 假设parseLine已实现 } } } // 实例化方式 auto reader = ThingReader!(typeof(f.byLine))(f);
方法B:添加静态工厂函数简化使用
为了避免每次都写typeof(f.byLine),可以给结构体加一个静态工厂方法,让编译器自动推导模板参数:
struct ThingReader(Lines) { Lines lines; Thing thing; this(File f) { this.lines = f.byLine; popFront; } // 其他方法和之前一样... // 静态工厂函数,自动推导Lines类型 static auto create(File f) { return ThingReader!(typeof(f.byLine))(f); } } // 使用方式更简洁 auto reader = ThingReader.create(f);
方案2:直接声明完整的ByLine类型(非模板方案)
如果你不想用模板,需要明确写出byLine返回的完整类型。首先确保导入std.stdio,然后指定ByLine的模板参数(默认是char类型的字符和换行符):
import std.stdio; struct ThingReader { // 完整的类型声明 std.stdio.ByLine!(char, char) lines; Thing thing; this(File f) { this.lines = f.byLine; popFront; } // 其他方法不变 }
不过这个方式灵活性差——如果后续你调用f.byLine!(wchar)或者byLine(keepTerminator: true),类型会变化,模板方案更适配这种场景。
方案3:利用D 2.081+的auto成员推导(最简单)
从D 2.081版本开始,结构体成员支持auto声明,只要在构造器中完成初始化,编译器会自动推导类型:
struct ThingReader { auto lines; // D 2.081及以上版本支持 Thing thing; this(File f) { this.lines = f.byLine; popFront; } // 其他方法不变 } // 直接实例化即可 auto reader = ThingReader(f);
这个方式最省心,但要注意你的编译器版本是否达标。
为什么之前写ByLine会报错?
你之前尝试ByLine或std.stdio.ByLine报错,是因为ByLine是一个模板类型,必须指定模板参数才能使用(比如ByLine!(char, char)),或者通过typeof(f.byLine)让编译器帮你推导完整类型。
内容的提问来源于stack exchange,提问作者neniu
相关产品推荐
相关产品推荐

