gpt4 book ai didi

c++ - 通过隐藏/取消隐藏代码行避免编写两个版本的函数

转载 作者:行者123 更新时间:2023-11-28 00:01:52 24 4
gpt4 key购买 nike

一个函数有两个版本(下面的代码是简化版)。程序中使用了两个版本。在实际功能中,两个版本的差异可能出现在两三个不同的地方。

如何通过模板或其他方式避免在不牺牲性能的情况下在代码中编写两个版本?这是一次尝试使代码更具可读性。

性能至关重要,因为它会运行很多次,我正在为不同的实现编写基准。

(此外,如果我正在为几个人编写一个库,这是一个好的 api 吗?)

例子:

int set_intersect(const int* A, const int s_a,
const int* B, const int s_b,
int* C = 0){

//if (int* C == 0), we are running version
//0 of the function.

//int* C is not known during compilation
//time for version 1.

int Count0 = 0;
//counter for version 0 of the function.

const int* const C_original(C);
//counter and pointer for version 1 of
//the function

int a = 0;
int b = 0;
int A_now;
int B_now;

while(a < s_a && b < s_b){
A_now = A[a];
B_now = B[b];
a += (A_now <= B_now);
b += (B_now <= A_now);
if (A_now == B_now){
if (C == 0){
Count0++;
} else {
C++;
*(C)=A_now;
}
}
}
if (C == 0){
return Count0;
}else{
return C - C_original;
}
}

谢谢。


更新:

Conditional compile-time inclusion/exclusion of code based on template argument(s)

(其中一些模板看起来很长)

Remove/Insert code at compile time without duplication in C++

(这与我的情况更相似。不过我的情况更简单。)


我想下面的方法可行,但它增加了一个新的论点。

int set_intersect(const int* A, const int s_a,
const int* B, const int s_b,
int* C = 0,
char flag);

将版本 0 的所有代码放入 if (flag == '0') { /* version 0 code */ }

将版本 1 的所有代码放入 if (flag == '1') { /* version 1 code */}

可能可以将标志变量放入模板中(如 Barmar 在评论中所建议的那样),这样就不会为函数添加另一个参数。也可以用枚举替换 0 和 1(如 enum class set_intersection_type {find_set, size_only} )。调用该函数将类似于 set_intersect<find_set>(const int* A, const int s_a, const int* B, const int s_b, int* C)set_intersect<size_only>(const int* A, const int s_a, const int* B, const int s_b)希望这比以前更具可读性,并且编译器足够聪明,可以看到发生了什么。

另一个问题是,如果有人使用 findset 版本(版本 1),然后忘记更改默认参数(int C* = 0)怎么办?可以这样调用函数:set_intersect<find_set>(const int* A, const int s_a, const int* B, const int s_b) .

也许我可以在评论中使用 dasblinkenlight 的想法。创建两个包装函数( set_intersectionset_intersection_size )。每个包装器使用不同的参数调用实际函数。还将实际函数列为私有(private)函数,因此没有人可以直接调用它。

对于集合交集的不同实现,也许可以创建一个带有模板的通用包装器。调用包装器类似于 set_intersection<basic> , set_intersection<binary_search> , 或 set_intersection_size<simd>等。这看起来更好。

最佳答案

一般看起来可行,问题是你是否想这样做。会说不。据我所知,您可以做两件不同的事情:

  1. 版本 0 计算交集的大小
  2. 版本 1 计算交集的大小,并将交集写入 C* 之后的位置,假设有足够的空间来存储它。

我不仅为了速度,而且为了清晰起见,制作两个不同的函数,set_intersectionset_intersection_size,但如果你坚持要一个,我会根据你的代码进行基准测试std::set_intersection , 如果可能的话,如果 C != 0 就重定向到::std 版本。

在您当前的版本中,我不会使用您的库。然而,我也很难想出这样一种情况,即我更喜欢 set_intersection 的定制版本而不是 STL 版本。如果我需要比 STL 更好的性能,我会期望将代码中的点确定为瓶颈,并且我根本不会使用库调用,而是自己编写代码,可能是在汇编和展开循环等过程中。 .

让我有点困扰的是它应该如何工作:

const int* const Count1(C);
//counter and pointer for version 1 of
//the function
...
Count1++;
*(Count1)=A_now;

关于c++ - 通过隐藏/取消隐藏代码行避免编写两个版本的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38276076/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com