2607d,d版概念

原文

D的概念

D语言中的模板约束是该语言最出色的功能之一.然而,当约束失败时,很难知道它失败的原因.该库提供一个说明用户自定义类型应实现编译时接口或概念的方式来解决它.

isInputRange.如果你不小心把空的拼成了empt,你的类型就不是输入区间,但尽管编译器知道,你也不知道为什么.

解决方法是使用可按UDA也可按静断使用的模型.

cpp 复制代码
import concepts.models: models;
void checkFoo(T)()
{
    T t = T.init;
    t.foo();
}
enum isFoo(T) = is(typeof(checkFoo!T));
@models!(Foo, isFoo)
//按`UDA`
struct Foo
{
    void foo() {}
    static assert(models!(Foo, isFoo));
//按静断
}
//仍可用作`模板约束`:
void useFoo(T)(auto ref T foo) if(isFoo!T) {
}

这里模板约束isFoo保证对类型成立.这与普通静断的区别在于,当动作失败时,checkFoo的代码仍会实例化,这样用户就知道它为何未能成功编译.dmd2.074示例错误信息:

cpp 复制代码
source/concepts/models.d(111,10): Error: no property 'foo' for type 'Foo', did you mean 'fo'
source/concepts/models.dmixin-42(42,1): Error: template instance concepts.models.checkFoo!(Foo) error instantiating
source/concepts/models.d(61,6):        instantiated from here: models!(Foo, isFoo)

该库还实现了d标准库区间模板约束版本,使其可用在模型上:

cpp 复制代码
import concepts: models, isInputRange;
@models!(Foo, isInputRange)
struct Foo {
//...
}

dmd2.074示例错误信息(已实现frontpopFront但未实现empty):

cpp 复制代码
source/concepts/range.d(13,10): Error: template std.range.primitives.empty cannot deduce function from argument types !()(B), candidates are:
/usr/include/dlang/dmd/std/range/primitives.d(2043,16):        std.range.primitives.empty(T)(in T[] a)
source/concepts/models.dmixin-42(42,1): Error: template instance concepts.range.checkInputRange!(B) error instantiating
source/concepts/range.d(72,6):        instantiated from here: models!(B, isInputRange)

使用D接口指定编译时模板约束

cpp 复制代码
interface IFoo {
    int foo(int i, string s) @safe;
    double lefoo(string s) @safe;
}
@implements!(Foo, IFoo)
struct Foo {
    int foo(int i, string s) @safe { return 0; }
    double lefoo(string s) @safe { return 0; }
}
//如下,无法编译
@implements!(Oops, IFoo)
struct Oops {}

其他示例

限制结构不包含成员函数(感谢@jmh530):

cpp 复制代码
void checkOnlyData(T)()
    if (is(T == struct))
{
    import std.traits : isFunction;
    static foreach (mem; __traits(allMembers, T))
    {
        static if (mem != "this")
        {
            static assert(!(isFunction!(__traits(getMember, T.init, mem))),
                          T.stringof ~ " is constrained to not have any member functions, but it has (at least) the member function: " ~ mem);
        }
    }
}
template isOnlyData(T)
    if (is(T == struct))
{
    enum isOnlyData = is(typeof(checkOnlyData!(T)));
}
@models!(Foo, isOnlyData)
struct Foo
{
    int a;
}
Foo foo;
相关推荐
fqbqrr2 天前
2607d,C++细节比不上d
c++·d
fqbqrr7 天前
2607d,parin游戏引擎
游戏引擎·d
fqbqrr8 天前
2607d,joka
d
fqbqrr2 个月前
2606d,用d语言构建游戏引擎
游戏引擎·d
fqbqrr2 个月前
2605d,d可以没有GC
d
fqbqrr4 个月前
2603,d去年9月会议
d
fqbqrr9 个月前
2510d,C++虚混杂
c++·d
fqbqrr2 年前
2501d,d作者,炮打C语言!
c语言·d
fqbqrr2 年前
2501d,d的优势之一与C互操作
d