假设我正在实现一个函数func
。
func
。func
,但是在该函数中将使用缺少的第二个参数的默认值。我可以想到三种实现此功能的方法:
void func(int a, long b = c);
func
将被这样调用:
func(a);
func(a, b);
void func(int a);
void func(int a, long b);
func
将被这样调用:
func(a);
func(a, b);
void func(int a, optional<long> b);
func
将被这样调用:
func(a, optional<long> ());
func(a, b);
我想知道实现所需功能的最佳方法是什么。欢迎任何建议。
答案 0 :(得分:2)
考虑此问题时有两个问题要问自己:
如果第二个参数具有逻辑默认值,并且该函数不管做什么都执行相同的操作,则默认参数可以正常工作。例如:
std::vector<std::string> split_string(const std::string& str, char sep = ' ');
默认情况下,这会在空格处分割字符串,但是可以使用分隔符来更改它。将其分为两个重载或在此处使用std::optional
毫无意义。
如果第二个参数没有逻辑默认值,但是如果没有给出该函数,则该函数在大多数情况下仍然相同,那么std::optional
就更有意义了。例如:
void extract(const std::filesystem::path& archive_file,
const std::filesystem::path& output_dir,
std::optional<std::regex> exclude_filter = {});
在这里,我们正在从存档文件中提取文件,并将提取的文件写入磁盘,可以选择排除与某些模式匹配的文件。使用或不使用过滤器,函数定义在根本上是相同的;这只是一个额外的区别:
if (exclude_filter && std::regex_match(file, *exclude_filter) continue;
重复定义没有多大意义,因此重载实际上没有任何意义。同时,没有“不匹配任何内容”的正则表达式,因此没有可以应用的逻辑默认过滤器。 std::optional
非常适合这里。
请注意,我仍然使用默认参数。将您的std::optional
设置为空可以使您的通话更加顺畅。
最后,如果函数实现在one-arg和two-arg版本之间根本不同,则请使用重载。例如:
void hide(window& win) {
win.set_visible(false);
}
template <typename rep, typename period>
void hide(window& win, const std::chrono::duration<rep, period>& fade_time) {
auto wait_time = equal_intervals(fade_time, win.opacity());
while (win.oapcity() > 0) {
win.set_opacity(win.opacity() - 1);
std::this_thread::sleep_for(wait_time);
}
}
在这里,我们正在隐藏一个具有可选淡出时间的窗口。尽管这些函数在逻辑上执行相同的操作,但实现方式却完全不同。具有相同的功能没有多大意义。尽管0
是逻辑上的默认淡入时间,但在此处使用默认参数仍然没有意义,因为您最终会遇到一个大的if
块:
if (fade_time == 0) {
// body of the first overload
} else {
// body of the second overload
}