使用新参数更新模板 Parameter/Recast 个模板

Update Template Parameter/Recast Template With New Parameter

我正在创建一个模板化类型名树。我正在为树结构使用元组。树中不是 leaf 的每个 Node 都将包含一个包含其他 NodesLeaves 的类型名元组。叶子将包含一个 size 和一个 offset 表示它们在元组中的位置(相对于根节点并基于它之前的叶节点的 size )。基本上所有值都将在编译时已知,我想将元组用作各种映射。最终结果将如下所示:

很简单,我创建了一个可变参数模板注释并将结果解压缩到节点的元组中

template<typename... Elements>
struct Node {
    std::tuple<Elements...> elements;
};

但要注意的是,我希望 Nodesleaves 都包含一个模板参数来表示它们在元组中的偏移位置,这样我就可以访问“Leaf 4”例如,通过使用 std::get<0>(std::get<1>(Node0)) 从节点 1 和从“节点 2”中,我可以访问它的元素,每个元素仍然知道它们在“更大的元组”中的偏移量。在编程上,这看起来像这样(尽管下面不考虑偏移部分):

template<uint16_t offset, uint16_t size>
struct Leaf {
    constexpr uint16_t GetOffset() {return offset; }
    constexpr uint16_t GetSize() {return size; }
};

template<uint16_t offset, typename... Elements>
struct Node {
    std::tuple<Elements...> elements;  //Does not setup proper offsets
    
    constexpr uint16_t GetOffset() { return offset; }
};

如您所见,我有一个元素元组,但我需要使用基于之前叶子大小的新偏移量将它们“重铸”到新模板中。所以,按照“重铸”的思路,我的下一个想法是:

template<uint16_t offset, uint16_t size>
struct Leaf {
    static constexpr uint16_t GetOffset() {return offset; }
    static constexpr uint16_t GetSize() {return size; }

    //New ability to Recast
    template<uint16_t newOffset>
    struct Recast {
        typedef Leaf<newOffset, size> type;
    };
};

template<uint16_t offset, typename... Elements>
struct Node {

    static constexpr uint16_t GetSize() {
        return (Elements::GetSize() + ...);
    }

    static constexpr auto GetElements() {
        uint16_t size = 0;
        //Using the comma operator to increment size before recasting using it
        return std::tuple<(Elements::template Recast<(size+= Elements::GetSize(), size)>::type)...>
    }
    static constexpr auto elements = GetElements();

    static constexpr uint16_t GetOffset() { return offset; }

    //New ability to Recast
    template<uint16_t newOffset>
    struct Recast {
        typedef Node<newOffset, Elements...> type;
    };
};

但现在我 运行 遇到了 size 不能用作常量表达式的问题,即使它是增量也会在它被用作偏移量之前出现由于使用逗号运算符的操作顺序而重铸。长话短说,我怎样才能使这个愿景成为现实,他们是我可以对现有设置进行的调整,还是我应该使用其他工具来帮助简化整个事情?

为了潜在地解决问题,我使用模板参数来存储偏移量,因为这样我可以确保它可以在编译时进行评估,这样就不需要存储这些值的数据内存了。基本上我想确保如果这些值无论如何都将被内联,那么它们也不会占用堆栈或堆上的 space。如果有另一种方法可以完成类似的事情,那也是完美的。

抱歉,如果我不太了解代码工作的确切逻辑,但您可以试试这个:

struct Node {
     ⋮
     ⋮
    template<uint16_t ... I, uint16_t ... J>
    static constexpr auto GetElements_helper(std::integer_sequence<uint16_t, I...>, std::integer_sequence<uint16_t, J...>)
    {
        constexpr std::array arr{I...};
        return std::tuple<typename Recast<std::accumulate(arr.begin(), arr.begin() + J + 1, uint16_t {})>::type...>{};
    }

    static constexpr auto GetElements()
    {
        return GetElements_helper(std::integer_sequence<uint16_t, Elements::GetSize()...>{}, std::make_integer_sequence<uint16_t, sizeof...(Elements)>{});
    }
     ⋮
     ⋮
}