我经常遇到这个问题,但没有找到解决方案。
我编写了一个对不同算法进行基准测试的程序。该程序根据命令行参数选择特定算法,例如
./我的程序算法特定名称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
}
...
正如你所看到的,这段代码有两个大问题:
我也无法强制对所有变体进行彻底检查。 当然,有像字符串化这样的 gcc 扩展,但这只能解决第一个问题,不能解决第二个问题,而且它不是标准的。
我想知道这个问题是否有解决方案。 所以我想在数据结构中也命名变量及其内容以供查找, 类似带有“包含”方法和详尽开关的字符串枚举。
当然上面的代码可以工作,但它并不是解决此类问题的完美解决方案,减少冗余就好了。
这不是一个完美的答案,因为它依赖于编译器。但至少对于 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,并且可以避免许多潜在的字符串副本!这段代码只是为了展示这个想法。