C++ 如何静态(按名称)和动态地存储和检索命名变量(字符串)

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

我经常遇到这个问题,但没有找到解决方案。

我编写了一个对不同算法进行基准测试的程序。该程序根据命令行参数选择特定算法,例如

./我的程序算法特定名称1

现在在代码中我正在这样做:

//define all algorithm names here on which we want to dispatch below
const std::string ALGORITHM_SPECIFIC_NAME1 = "algorithm_specific_name1";
const std::string ALGORITHM_SPECIFIC_NAME2 = "algorithm_specific_name2";
...
//define data structure for dynamic lookup of algorithm name based on command-line-argument
const std::vector<std::string> ALL_ALGORITHMS{ALGORITHM_SPECIFIC_NAME1, ALGORITHM_SPECIFIC_NAME2, ... };

//usage of command-line-arguments
const std::vector<std::string> arguments{argv + 1, argv + argc};
const std::string algorithm_argument = arguments[0];

//check if given argument is valid choice of algorithm
if (std::find(ALL_ALGORITHMS.begin(), ALL_ALGORITHMS.end(), algorithm_argument) == ALL_ALGORITHMS.end()) {
    std::cerr << "No valid algorithm selected: " << algorithm_argument << std::endl;
    return -1;
}
   
std::cout << "Using " << algorithm_argument << std::endl;

//dispatch on specific name of algorithm because ALL_ALGORITHMS[0] would not be very descriptive
if (algorithm_argument == ALGORITHM_SPECIFIC_NAME1) {
    //call algorithm one
}
if (algorithm_argument == ALGORITHM_SPECIFIC_NAME2) {
    //call algorithm two
}
...

正如你所看到的,这段代码有两个大问题:

  1. 算法常量的名称与其内容相同(大写/小写除外),当然不一定是这种情况,但我仍然必须为本质上相同的东西定义两个名称
  2. 在某些数据结构中手动插入所有字符串常量以进行查找 - 因此有两个地方需要更改,这是容易出错的

我也无法强制对所有变体进行彻底检查。 当然,有像字符串化这样的 gcc 扩展,但这只能解决第一个问题,不能解决第二个问题,而且它不是标准的。

我想知道这个问题是否有解决方案。 所以我想在数据结构中也命名变量及其内容以供查找, 类似带有“包含”方法和详尽开关的字符串枚举。

当然上面的代码可以工作,但它并不是解决此类问题的完美解决方案,减少冗余就好了。

c++ dynamic enums static command-line-arguments
1个回答
0
投票

这不是一个完美的答案,因为它依赖于编译器。但至少对于 clang 和 gcc 来说,可以获得全局函数的名称:

void alg_1() {}
void alg_2() {}

template<auto algorithm>
std::string get_algorithm_name() {
    std::string function_name = std::source_location::current().function_name();

    // function name contains a compiler dependent string representing the function
    // At least for latest clang and gcc it contains the name of the functions passed as "algorithm"

    return function_name;
}

template<auto algorithm>
void check_algorithm(std::string_view desired) {
    auto algorithm_name = get_algorithm_name<algorithm>();
    if (algorithm_name == desired) {
        algorithm();
    }
}

template<auto... algorithms>
struct AlgorithmList {
    static void execute(std::string_view desired) {
        ((check_algorithm<algorithms>(desired)), ...);
    }
};

int main() {
    using MyAlgorithms = AlgorithmList<alg_1, alg_2>;

    static const std::string_view example = "alg_1";
    MyAlgorithms::execute(example);
}

这个例子显然不完整,但它展示了这个想法。适用于大多数

function_name()
格式的解析例程可能需要依赖更多假设。例如,您始终可以以特定前缀启动算法函数,因此解析可以简单地查找该前缀。

godbold 上检查不同编译器的输出。

注意:已经做了0优化!可以将事物制作为 constexpr,并且可以避免许多潜在的字符串副本!这段代码只是为了展示这个想法。

© www.soinside.com 2019 - 2024. All rights reserved.