将 bool 变量作为参数传递的更好方法?
Better way to pass bool variable as parameter?
我想知道是否有更好的方法来编写它以获得更好的可读性。
如果您有如下功能,
void animal(bool hasFourLegs, bool hasHead, bool hasBody);
当你调用这个函数时,你最终会得到类似
的东西
animal(true, false, true);
这让我每次遇到这样的函数都会去看看定义。
所以...
我就是这样做的!
const bool HAS_FOURLEGS = true;
const bool NO_HEAD = false;
const bool HAS_BODY = true;
animal(HAS_FOURLEGS, NO_HEAD, HAS_BODY);
但我不喜欢在每次调用函数时都声明const bool
。
CPP 好像不支持
animal(bool hasFourlegs = true, bool hasHead = false, bool hasBody = true);
有没有更好更短的方法?
使用标志:
enum {
HAS_LEGS = 0x01,
HAS_HEAD = 0x02,
HAS_BODY = 0x04,
};
void animal(int properties);
animal(HAS_LEGS | HAS_HEAD);
当我 运行 遇到与此相关的问题时,我有时会创建一个 enum
即使只有 2 个预期选择:
例如,代替下面的函数声明:
bool search(..., bool recursive);
我会选择:
enum class SearchOpt
{
Recursive,
NonRecursive
};
bool search(..., SearchOpt opt);
因此,调用语法更改为:
bool found = search(..., true);
至:
bool found = search(..., SearchOpt::Recursive);
注意:这样可以避免每次调用该函数时都必须创建自己的常量。
编辑
正如其他人所建议的那样,与其为每个选项设置单独的 bool
并因此为每个选项设置单独的 enum
,不如将单个 enum
配置为 bit旗帜。
评论是你的朋友!
animal( true, //hasFourLegs
false, //hasHead
true //hasBody
);
您可以使用按位值,如下所示:
const int hasLegs = 0x01;
const int noHead = 0x02;
const int hasBody = 0x04;
然后调用 animal
并使用以上任意组合,例如:
动物(有腿+有身体);
Decalre animal
带有一个 int
参数。
inside `animal`, test the bits:
if (parameter & haasBody)
{
// it has a body....
}
另一种选择是使用 class 在它们密切相关的地方保存参数:
struct AnimalOptions {
bool hasHead, hasBody, hasLegs;
AnimalOptions() : hasHead(false), hasBody(false), hasLegs(false);
}
...
AnimalOptions opt;
opt.hasHead = true;
animal(opt);
只要您的函数似乎采用了一堆具有相同类型的参数,而且它们的顺序不容易记住,这种技术就会很有用。当您的函数需要几个 int
时,它同样有用。
奇怪,没有人建议来自 Boost.parameter 的命名参数:http://www.boost.org/doc/libs/1_59_0/libs/parameter/doc/html/index.html
作为其他答案的替代方案,我喜欢 tagged_bool that Andrzej Krzemieński 在他的博客上提出的。
C++20 将 designated initializers 作为聚合初始化的一部分。您可以使用布尔参数创建结构并按值传递结构。您甚至可以使用默认参数值。
struct AnimalParts {
bool hasFourLegs = false;
bool hasHead = true;
bool hasBody = true;
}
void animal(AnimalParts parts);
然后像这样使用它:
animal({.hasFourLegs = true, .hasHead = false});
这与您建议的命名参数习语非常接近。在编译方面,这两个选项似乎都产生了可比较的输出,参见 Godbolt.
我不确定这是正确的做法,但我还是忍不住要分享这个想法。
让我们假设该函数不是您的,而是来自一些难以更改的流行API。
void animal(bool hasFourLegs, bool hasHead, bool hasBody);
在这种情况下,可以这样调用它:
animal(bool("hasFourlegs"), !bool("hasHead"), bool("hasBody"));
C-string始终是一个非零指针,转换为true
。
一个可能的缺点是编译时间...?
另一个是代码行长度的增加...
我想知道是否有更好的方法来编写它以获得更好的可读性。 如果您有如下功能,
void animal(bool hasFourLegs, bool hasHead, bool hasBody);
当你调用这个函数时,你最终会得到类似
的东西animal(true, false, true);
这让我每次遇到这样的函数都会去看看定义。
所以...
我就是这样做的!
const bool HAS_FOURLEGS = true;
const bool NO_HEAD = false;
const bool HAS_BODY = true;
animal(HAS_FOURLEGS, NO_HEAD, HAS_BODY);
但我不喜欢在每次调用函数时都声明const bool
。
CPP 好像不支持
animal(bool hasFourlegs = true, bool hasHead = false, bool hasBody = true);
有没有更好更短的方法?
使用标志:
enum {
HAS_LEGS = 0x01,
HAS_HEAD = 0x02,
HAS_BODY = 0x04,
};
void animal(int properties);
animal(HAS_LEGS | HAS_HEAD);
当我 运行 遇到与此相关的问题时,我有时会创建一个 enum
即使只有 2 个预期选择:
例如,代替下面的函数声明:
bool search(..., bool recursive);
我会选择:
enum class SearchOpt
{
Recursive,
NonRecursive
};
bool search(..., SearchOpt opt);
因此,调用语法更改为:
bool found = search(..., true);
至:
bool found = search(..., SearchOpt::Recursive);
注意:这样可以避免每次调用该函数时都必须创建自己的常量。
编辑
正如其他人所建议的那样,与其为每个选项设置单独的 bool
并因此为每个选项设置单独的 enum
,不如将单个 enum
配置为 bit旗帜。
评论是你的朋友!
animal( true, //hasFourLegs
false, //hasHead
true //hasBody
);
您可以使用按位值,如下所示:
const int hasLegs = 0x01;
const int noHead = 0x02;
const int hasBody = 0x04;
然后调用 animal
并使用以上任意组合,例如:
动物(有腿+有身体);
Decalre animal
带有一个 int
参数。
inside `animal`, test the bits:
if (parameter & haasBody)
{
// it has a body....
}
另一种选择是使用 class 在它们密切相关的地方保存参数:
struct AnimalOptions {
bool hasHead, hasBody, hasLegs;
AnimalOptions() : hasHead(false), hasBody(false), hasLegs(false);
}
...
AnimalOptions opt;
opt.hasHead = true;
animal(opt);
只要您的函数似乎采用了一堆具有相同类型的参数,而且它们的顺序不容易记住,这种技术就会很有用。当您的函数需要几个 int
时,它同样有用。
奇怪,没有人建议来自 Boost.parameter 的命名参数:http://www.boost.org/doc/libs/1_59_0/libs/parameter/doc/html/index.html
作为其他答案的替代方案,我喜欢 tagged_bool that Andrzej Krzemieński 在他的博客上提出的。
C++20 将 designated initializers 作为聚合初始化的一部分。您可以使用布尔参数创建结构并按值传递结构。您甚至可以使用默认参数值。
struct AnimalParts {
bool hasFourLegs = false;
bool hasHead = true;
bool hasBody = true;
}
void animal(AnimalParts parts);
然后像这样使用它:
animal({.hasFourLegs = true, .hasHead = false});
这与您建议的命名参数习语非常接近。在编译方面,这两个选项似乎都产生了可比较的输出,参见 Godbolt.
我不确定这是正确的做法,但我还是忍不住要分享这个想法。
让我们假设该函数不是您的,而是来自一些难以更改的流行API。
void animal(bool hasFourLegs, bool hasHead, bool hasBody);
在这种情况下,可以这样调用它:
animal(bool("hasFourlegs"), !bool("hasHead"), bool("hasBody"));
C-string始终是一个非零指针,转换为true
。
一个可能的缺点是编译时间...? 另一个是代码行长度的增加...