You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

D语言(LDC2)模板函数调用时delegate推导为void及自定义Option问题

搞定D语言LDC2下基于Algebraic实现Option类型的模板函数问题

我来帮你梳理并解决你遇到的这两个问题:模板函数调用时delegate被推导为void,还有getValue、isDefined便利函数的实现问题。

首先先把你的Option类型定义补全并优化下,确保基础结构没问题:

import std.variant;

struct None{};
struct Some(T){
    T t;
    alias t this;
    T get(){ return t; }
};
alias Option(T) = Algebraic!(Some!(T), None);

Option!T some(T)(T t){
    return Option!T(Some!T(t));
}

Option!T none(T)(){
    return Option!T(None());
}

接下来逐个解决问题:

1. 实现正确的getValue和isDefined函数

你之前写的函数里VariantN!(size, Some!T, None)其实没必要这么写,因为Option!T本身就是Algebraic的别名,而Algebraic已经封装了VariantN的细节,直接用Option!T当参数就行。

getValue函数

这个函数要从Some类型里安全取值,最好先做类型检查,避免运行时崩溃:

T getValue(T)(Option!T opt){
    // 用peek方法安全检查是否是Some类型
    if (auto someVal = opt.peek!(Some!T)){
        return someVal.t;
    }
    // 这里可以根据需求抛异常或者返回T的默认值
    throw new Exception("当前Option是None,无法获取值");
}

isDefined函数

判断Option是不是Some类型,直接用Algebraic自带的has方法最方便:

bool isDefined(T)(Option!T opt){
    return opt.has!(Some!T);
}

2. 解决delegate被推导为void的问题

这种情况一般是编译器没法正确推断delegate的类型,大概率是模板函数的签名不够明确,或者传递的delegate参数有歧义。

举个例子,如果你的模板函数是这样的:

void processOption(T)(Option!T opt, delegate(T) handler){
    if (opt.isDefined!T){
        handler(opt.getValue!T);
    }
}

调用时如果编译器推导出错,你可以显式指定模板参数帮它一把:

auto myOpt = some(42);
processOption!int(myOpt, (int val) => writeln(val));

或者调整函数签名,把delegate的类型和Option的T绑定死,让编译器更容易推断:

void processOption(T)(Option!T opt, void delegate(T) handler){
    if (opt.isDefined!T){
        handler(opt.getValue!T);
    }
}

这样调用的时候,编译器能通过Option!T的T自动推断delegate的参数类型,就不会乱推导成void了。

另外用lambda的时候,尽量让参数类型明确,或者利用D的自动推断,比如:

myOpt.processOption((val) => writeln(val));
// 只要processOption的签名正确,编译器会自动知道val是int类型

测试一下效果

把这些代码拼起来跑个测试:

import std.stdio;

void main(){
    Option!int opt1 = some(100);
    Option!int opt2 = none!int();

    writeln(opt1.isDefined!int); // 输出true
    writeln(opt2.isDefined!int); // 输出false

    writeln(opt1.getValue!int); // 输出100
    // opt2.getValue!int; // 取消注释会抛出异常

    opt1.processOption!int((int val) => writeln("处理值:", val)); // 输出"处理值:100"
}

内容的提问来源于stack exchange,提问作者Russoul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:01:03