5

我有一个关于 C++ 中“良好设计实践”的问题。我正在用 C++11 编写一个数值库,并且我使用了大量的元编程和基于模板的技术。但我有一个非常基本的问题:

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


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

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

2)使用模板参数:

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

3)使用可变参数:

myFunction(..., const bool flag);

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

编辑:对于所考虑的函数,运行时开销可以被认为是微不足道的,所以这不是最关键的一点。

编辑2:我知道这三个都有效。但由于我的图书馆会有用户,它需要有一个可靠/好的设计。

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

4

5 回答 5

11

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

enum class MyFunctionMode { EnableFoo, DisableFoo };

void myFunction(..., MyFunctionMode mode);

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

于 2012-10-03T19:31:52.073 回答
2

我的建议是使用选项 1。

注释:

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

我的 2 美分。

于 2012-10-03T19:24:20.550 回答
0

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

在第三个中是可以接受的,但 if 语句将在运行时进行评估,并且意味着浪费时间。

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

于 2012-10-03T19:26:36.447 回答
0

你可以做所有你知道的三个。

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.
于 2012-10-03T19:29:18.607 回答
0

复制非平凡代码是最糟糕的选择。如果这两个函数只是分派给实际有趣的函数,那么它可能是正确的选择。当然,这两个函数可以分派到模板版本,但它们可以更好地指示差异是什么,true或者false可以做什么。

另一个问题是函数的实际使用方式:如果它们本身是从具有相同配置或可以派生标志选择的配置的函数调用的,则使用不同的名称会变得相当烦人甚至不可维护:您最终会得到必须有条件地调用函数:

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

其他两个版本之间的选择归结为一个问题:支票重要吗?如果是这样,则模板是唯一的选择。如果不是,您可以选择任何一个版本,我敢打赌,匿名投票会投票支持运行时版本:当我向他们展示一个微不足道的模板时,我的大多数同事的眼睛都会眨眨眼。

于 2012-10-03T19:44:06.613 回答