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

移植Crafting Interpreters Java代码到C++如何处理Object类型literal字段

解决方案

你可以直接使用C++标准库提供的类型擦除容器实现需求,不需要自己编写继承体系,对应两种场景可选:

方案1:优先使用std::variant(推荐,适配解释器场景)

解释器中字面量的类型是固定有限的,只会是空值、数字、字符串、布尔值几种,std::variant性能更高、类型安全,没有额外的运行时开销:

  1. 首先定义字面量可承载的类型集合,用std::monostate对应Java的null空值:
#include <variant>
// 空值占位类型对应Java null,按需扩展后面的类型列表即可
using Literal = std::variant<std::monostate, double, std::string, bool>;
  1. 改写Token类:
class Token {
private:
    TokenType type;
    std::string lexeme;
    std::size_t col;
    std::size_t line;
    Literal literal;

public:
    // 对应无literal的构造场景
    Token(TokenType type, std::string lexeme, std::size_t col, std::size_t line)
        : type(type), lexeme(std::move(lexeme)), col(col), line(line), literal(std::monostate{}) {}
    
    // 对应带literal的构造场景
    Token(TokenType type, std::string lexeme, Literal literal, std::size_t col, std::size_t line)
        : type(type), lexeme(std::move(lexeme)), literal(std::move(literal)), col(col), line(line) {}
    
    std::string to_string() const {
        std::string literal_str;
        std::visit([&](auto&& arg) {
            using T = std::decay_t<decltype(arg)>;
            if constexpr (std::is_same_v<T, std::monostate>) {
                literal_str = "null";
            } else if constexpr (std::is_same_v<T, double>) {
                literal_str = std::to_string(arg);
            } else if constexpr (std::is_same_v<T, std::string>) {
                literal_str = arg;
            } else if constexpr (std::is_same_v<T, bool>) {
                literal_str = arg ? "true" : "false";
            }
        }, literal);
        // 补充TokenType转字符串逻辑后拼接返回即可
        return tokenType_to_string(type) + " " + lexeme + " " + literal_str;
    }
};
  1. 对应实现addToken重载即可:
void addToken(TokenType type) {
    addToken(type, std::monostate{});
}

void addToken(TokenType type, Literal literal) {
    std::string text = source.substr(start, current - start);
    tokens.emplace_back(type, std::move(text), std::move(literal), col, line);
}

方案2:使用std::any适配完全任意类型

如果后续确实需要承载未提前定义的任意类型,可以用std::any,只需要在取值时做类型校验:

#include <any>

class Token {
private:
    TokenType type;
    std::string lexeme;
    std::size_t col;
    std::size_t line;
    std::any literal;

public:
    Token(TokenType type, std::string lexeme, std::size_t col, std::size_t line)
        : type(type), lexeme(std::move(lexeme)), col(col), line(line) {}
    
    template<typename T>
    Token(TokenType type, std::string lexeme, T&& literal_val, std::size_t col, std::size_t line)
        : type(type), lexeme(std::move(lexeme)), literal(std::forward<T>(literal_val)), col(col), line(line) {}
    
    // 取值时使用std::any_cast即可,可捕获bad_any_cast异常处理类型不匹配场景
};

两种方案都需要C++17及以上标准支持,目前主流编译器都默认支持该标准。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 18:39:01