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

如何在程序启动时通过类收集编译期常量字符串信息?

解决方案

一、基于类的运行期注册方案(满足main启动时可用)

核心思路是利用C++全局对象构造函数在main执行前调用的特性,结合单例Holder类实现字符串的提前注册:

1. Holder类实现

// Holder.h
#pragma once
#include <vector>
#include <string>

class Holder {
public:
    // 静态注册方法,供外部组件调用
    static void registerInfo(const std::string& info) {
        getInstance().data_list.push_back(info);
    }

    // 获取所有已注册的字符串列表
    static const std::vector<std::string>& getRegisteredInfos() {
        return getInstance().data_list;
    }

private:
    // 私有构造,确保单例
    Holder() = default;
    Holder(const Holder&) = delete;
    Holder& operator=(const Holder&) = delete;

    // 单例实例获取逻辑
    static Holder& getInstance() {
        static Holder instance;
        return instance;
    }

    // 存储注册字符串的容器
    std::vector<std::string> data_list;
};

2. 组件侧注册实现

在需要注册字符串的组件中,定义全局静态实例,借助其构造函数完成注册:

// Comp.h
#pragma once
#include "Holder.h"

class Comp {
public:
    Comp() {
        Holder::registerInfo("some information from Comp");
    }
};

// 全局实例触发构造,在main前完成注册
static Comp comp_instance;

3. main函数中使用

#include <iostream>
#include "Holder.h"

int main() {
    const auto& infos = Holder::getRegisteredInfos();
    for (const auto& info : infos) {
        std::cout << info << std::endl;
    }
    return 0;
}

注意:全局对象的构造顺序不固定,若多个组件存在依赖关系需额外处理;多线程环境下动态注册需加锁(但main前初始化通常为单线程,无需额外处理)。

二、编译期注册方案

若要完全在编译期完成字符串收集,避免运行时初始化的不确定性,可采用以下方案:

1. 模板元编程+全局变量初始化

// Holder.h
#pragma once
#include <vector>
#include <string>

namespace detail {
    // 全局容器存储编译期注册的字符串
    inline std::vector<std::string> compile_time_infos;

    // 模板类触发注册动作
    template<const char* Str>
    struct Register {
        Register() {
            compile_time_infos.push_back(Str);
        }
    };
}

class Holder {
public:
    static const std::vector<std::string>& getCompileTimeInfos() {
        return detail::compile_time_infos;
    }
};

// 宏简化注册流程
#define REGISTER_COMPILE_INFO(STR) \
    inline const char str_##__LINE__[] = STR; \
    detail::Register<str_##__LINE__> reg_##__LINE__;

2. 组件侧注册方式

// Comp.cpp
#include "Holder.h"

// 编译期注册字符串
REGISTER_COMPILE_INFO("compile time info from Comp");

3. 更纯粹的C++20编译期方案

利用constexpr和模板拼接,完全在编译期构建字符串数组:

// Holder.h
#pragma once
#include <array>
#include <string_view>

// 单个注册项的容器
template<std::string_view... Strs>
struct CompileTimeHolder {
    static constexpr std::array<std::string_view, sizeof...(Strs)> infos = {Strs...};
};

// 拼接多个注册项的模板逻辑
template<typename H1, typename H2>
struct MergeHolder;

template<std::string_view... S1, std::string_view... S2>
struct MergeHolder<CompileTimeHolder<S1...>, CompileTimeHolder<S2...>> {
    using type = CompileTimeHolder<S1..., S2...>;
};

// 宏定义单个注册
#define REGISTER_COMPILE_STR(STR) \
    using CompReg_##__LINE__ = CompileTimeHolder<STR>;

// 宏合并所有注册项
#define MERGE_ALL_REGISTERS(...) \
    using AllRegistrations = MergeHolder<__VA_ARGS__>::type;

使用示例:

// Comp1.cpp
#include "Holder.h"
REGISTER_COMPILE_STR("info 1")

// Comp2.cpp
#include "Holder.h"
REGISTER_COMPILE_STR("info 2")

// main.cpp
#include <iostream>
#include "Holder.h"
MERGE_ALL_REGISTERS(CompReg_1, CompReg_2)

int main() {
    for (const auto& info : AllRegistrations::infos) {
        std::cout << info << std::endl;
    }
    return 0;
}

该方案无运行时开销,所有字符串在编译期完成收集,但需要C++20及以上版本支持。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 23:54:59