C++设计:具有布尔选项的函数

C++ design : functions with boolean options

本文关键字:选项 函数 布尔 设计 C++      更新时间:2023-10-16

我有一个关于C++中"良好设计实践"的问题。我正在用C++11编写一个数字库,我使用了很多元编程和基于模板的技术。但我有一个非常基本的问题:

考虑一个函数,它可以有两个非常接近的行为,但可以通过布尔标志激活的选项除外。我只考虑一个可以由开发人员设置/取消设置的标志,而不是一个可以在运行时设置/取消的标志。设计有三种可能性:


1)编写两个名称中带有显式选项的函数:

myFunctionFlag1(...);
myFunctionFlag2(...); 

2) 使用模板参数:

template<bool Flag> myFunction(...);

3) 使用可变参数:

myFunction(..., const bool flag);

就良好设计实践而言,哪种解决方案是可接受/不可接受的?如果有最好的解决方案,那是哪一个?为什么?如果有最糟糕的解决方案,那是哪一个?为什么?

EDIT:对于所考虑的函数,运行时开销可以忽略不计,所以这不是最关键的一点。

第二版:我知道这三个都有效。但由于我的图书馆将有用户,它需要有一个可靠/良好的设计。

选项2是否常见(因为在我看来这是一个很好的折衷方案)?

以上都不是。布尔标志对代码的可读性非常不利。如果标志控制的功能足够小,使用单个功能是有意义的,那么使用单个功能,但不要使用bool作为标志的类型。相反,使用具有有用名称的枚举器的枚举:

enum class MyFunctionMode { EnableFoo, DisableFoo };
void myFunction(..., MyFunctionMode mode);

这种模式使得在调用站点很容易理解为函数提供了哪些选项。可以使用标志组合多个选项。

我的建议是使用选项1。

评论:

  1. 最简单明了。它没有运行时开销
  2. 我认为使用这种方法没有足够的理由(如果提供更多细节,这种理由可能仍然存在)。它比选项1更复杂
  3. 此变体具有运行时开销。它仍然可以在非时间/CPU关键代码中使用。如果你的函数很大(超过100行),那么这个变体会变得更有吸引力

我的2美分。

您的第一个解决方案重复代码,这是没有人愿意做的事情。

在第三种情况下,if语句是可以接受的,但是if语句将在运行时进行求值,这意味着浪费时间。

模板一似乎是合适的。if语句在编译时将是另一个if (true)if (false),编译器将对其进行优化,就好像它们是no if语句一样。

你可以做到你所知道的三件事。

void fun_that_does_stuff();
void fun_that_does_something_else();
template < bool F >
void fun_that_does_stuff_or_something();
template < >
void fun_that_does_stuff_or_something<true>() { fun_that_does_stuff(); }
... blah blah.

复制非平凡的代码是最糟糕的选择。如果这两个函数只对实际感兴趣的函数进行调度,那么这可能是正确的选择。当然,这两个函数可以调度到模板化版本,但它们可以比truefalse更好地指示差异

另一个令人担忧的问题是函数的实际使用方式:如果它们本身是从具有相同配置或配置的函数中调用的,则使用不同的名称会变得相当烦人,甚至不可维护:您最终不得不有条件地调用函数:

(flag? &myFunctionFlag1: &myFunctionFlag2)(...);

在其他两个版本之间的选择归结为一个问题:支票重要吗?如果是,模板是唯一的选择。如果没有,你可以选择任何一个版本,我敢打赌,匿名投票会投票给运行时版本:当我向我的大多数同事展示一个琐碎的模板时,他们的眼睛都会闪闪发光。