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

C++中实现类Lisp的编译期constexpr cons链表

编译期Lisp风格Cons链表的C++实现

我一眼就发现你代码里的核心问题啦——你的pair结构体还没实现编译期可访问的car/cdr接口,而且缺少Lisp里必不可少的**空列表(nil)**终结类型,也没体现出cons链表递归嵌套的模板结构。咱们一步步把它补全,实现一个纯编译期的cons链表:

第一步:定义空列表标记与基础cons节点

首先需要一个专门的类型表示空列表,然后完善pair(也就是cons节点)的模板,确保所有操作都是constexpr的:

#include <type_traits>
#include <iostream>

namespace chops {
// 空列表的标记类型,对应Lisp里的nil
struct nil_t {};
constexpr nil_t nil;

// 基础cons节点模板,E1是当前元素,E2是后续链表(可以是另一个pair或者nil_t)
template <typename E1, typename E2>
struct pair {
    constexpr pair(const E1& car, const E2& cdr) : _car{car}, _cdr{cdr} {}

    // 编译期访问car和cdr
    constexpr const E1& car() const noexcept { return _car; }
    constexpr const E2& cdr() const noexcept { return _cdr; }

private:
    E1 _car;
    E2 _cdr;
};

// 辅助函数,简化cons节点的创建(类似Lisp的cons函数)
template <typename E1, typename E2>
constexpr auto cons(const E1& car, const E2& cdr) {
    return pair<E1, E2>{car, cdr};
}
} // namespace chops

第二步:编译期操作的实现

有了基础结构,咱们可以实现一些编译期的链表操作,比如计算链表长度:

namespace chops {
// 编译期计算链表长度的递归模板
template <typename List>
constexpr auto length(const List&) {
    if constexpr (std::is_same_v<List, nil_t>) {
        return 0;
    } else {
        return 1 + length(List{}.cdr());
    }
}

// 编译期遍历链表(运行时打印,也可以改成编译期生成值)
template <typename List>
void print(const List& list) {
    if constexpr (std::is_same_v<List, nil_t>) {
        std::cout << "nil\n";
    } else {
        std::cout << list.car() << " -> ";
        print(list.cdr());
    }
}
} // namespace chops

第三步:使用示例

现在你可以在编译期创建链表,甚至让编译器计算链表长度:

int main() {
    // 编译期创建链表: 1 -> 2 -> 3 -> nil
    constexpr auto my_list = chops::cons(1, chops::cons(2, chops::cons(3, chops::nil)));

    // 编译期计算长度,结果是3
    constexpr auto len = chops::length(my_list);
    static_assert(len == 3, "Length should be 3");

    // 运行时打印链表
    chops::print(my_list); // 输出: 1 -> 2 -> 3 -> nil

    return 0;
}

关键细节说明

  • 空列表的处理:用nil_t作为链表的终结类型,通过std::is_same_v在编译期判断是否到达链表末尾
  • constexpr的严格性:所有构造函数、访问器、辅助函数都标记为constexpr,确保可以在编译期执行
  • 模板递归:链表的结构是递归的pair<Elem, pair<...>>,直到最后一个节点的cdr是nil_t

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:12:22