C++ 在 constexpr 中合成链表

问题描述 投票:0回答:1

我有以下问题,考虑这样的链表:

struct Element {
 struct Element* const next; // the const is required here

 constexpr Car(struct Element* _nxt)
 : next(_nxt)
 { }
};

struct Element* const nil = NULL;

// there are a lot of subclasses for Element, like this
struct Car: public Element {
 int speed;
 
 constexpr Car(int _speed, Element* nxt = nil)
 : Element(nxt)
 , speed(_speed)
 { }
};

这个链表必须在像这样的 constexpr 容器中“合成”。请注意,所有不同的子类都可以保存在这个容器中。

template <typename... Args>
struct ElementContainer: public tuple<Args...> {
 constexpr /* important! */ ElementContainer(Args&&... args)
 : tuple<Args...>(forward(Args)(args)...)
 { }
};

这个函数的用法应该是这样的:

constexpr ElementContainer cont = {
 Car(10)
 , OtherSubclass(20, 30, "")
};

容器应该将列表合成在一起,以便整个构造在内存中看起来像这样:

Container:
 nxt -> &Car1
 tuple<Car, OtherSubclass>
  Car:
   nxt -> &OtherSubclass
   speed: 10
  OtherSubclass:
   next -> nil
   /* other data */
c++ linked-list constexpr stdtuple
1个回答
1
投票

创建一个“constexpr for”函数:

#include <utility>

template <typename Integer, Integer ...I, typename F>
constexpr void const_for_each(std::integer_sequence<Integer, I...>, F &&func)
{
    (func(std::integral_constant<Integer, I>{}) , ...);
}

template <auto N, typename F>
constexpr void const_for(F &&func)
{
    if constexpr (N > 0)
        const_for_each(std::make_integer_sequence<decltype(N), N>{}, std::forward<F>(func));
}

其余的都是微不足道的(将其放入构造函数中,如果您从元组继承,则

x
=
*this
)。

const_for<sizeof...(Args) - 1>([&](auto index)
{
    std::get<index.value>(x).next = &std::get<index.value + 1>(x);
});
© www.soinside.com 2019 - 2024. All rights reserved.