templates - D 中的结构体和元组模板参数

标签 templates d template-meta-programming

是否可以编写一个模板函数来增加不同结构的(数字)字段?例如:

struct Color
{
    ubyte a,r,g,b;
}

struct Point
{
    double x, y;
}

我尝试过这样的事情:

T update(T, A)(T t, A a)
if (is(T == struct))
{
    auto vals = t.tupleof;
    foreach (i; 0 .. vals.length) {
        vals[i] += a; // error: i cannot be read at compile time
    }
    return T(vals); // convert back to struct
}

我还尝试编写接受元组的函数模板,但元组始终会扩展,这会阻止编译器匹配正确的模板。 谢谢。

最佳答案

嗯,我想说你正在尝试做的事情相当奇怪,但这当然是可能的。最天真的、就地的方式可能是:

void update(T)(ref T t)
    if(is(T == struct))
{
    foreach(ref var; t.tupleof)
        ++var;
}

使用副本执行此操作的最简单方法可能是复制它,然后更新它,而不是尝试使用更新的值构造一个新副本(尽管我确信如果您真的想要的话,也可以这样做):

T update(T)(T t)
    if(is(T == struct))
{
    auto copy = t;

    foreach(ref var; copy.tupleof)
        ++var;

    return copy;
}

当然,这里的主要问题是对这两者的模板约束太弱。您所要做的就是在结构中具有不可递增的类型,这是行不通的。解决这个问题的最简单方法可能是创建一个同名模板来为您进行测试:

T update(T)(T t)
    if(isIncrementableStruct!T)
{
    auto copy = t;

    foreach(ref var; copy.tupleof)
        ++var;

    return copy;
}

template isIncrementableStruct(T)
{
    enum isIncrementableStruct = is(T == struct) &&
                                 is(typeof({T t; foreach(var; t.tupleof) ++var;}));
}

如果您希望能够递增所有可递增的字段并保留其他字段,您可能会执行以下操作:

T update(T)(T t)
    if(is(T == struct))
{
    auto copy = t;

    foreach(ref var; copy.tupleof)
    {
        static if(canIncrement!(typeof(var)))
            ++var;
    }

    return copy;
}

template canIncrement(T)
{
    enum canIncrement = is(typeof({T var; ++var;}));
}

无论如何,您似乎错过的主要事情是在使用 ref 时尝试直接迭代 tupleof ,以便更新元素而不是拥有副本其中正在更新。

关于templates - D 中的结构体和元组模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10957744/

相关文章:

c++ - 使用模板参数的静态成员模板

C++持久化数据

compiler-errors - D中逗号表达式的结果

d - 无法在 D 中的编译时递归地将 BigInt 乘以一定数量的迭代

c++ - 在编译时确定最小共同祖先

c++ - 编译器无法识别模板化的类

可迭代类的 C++ 函数重载

compiler-construction - LLVM 对 AVR 的支持如何适用于不同的语言?

c++ - 在编译时动态生成结构

c++ - 在 constexpr 函数中实例化多个模板