如何优雅地实现具有可变输出的单个方法?

How to elegantly implement single methods with variable output?

本文关键字:输出 单个 方法 何优雅 实现      更新时间:2023-10-16

我正在尝试改进我的代码风格。

有时我有执行复杂检查或计算的方法,根据调用方法的上下文,我需要从这些算法中获得不同的结果。假设有一个结果,它总是需要的,它将是方法的返回值。但是如何处理可选的其他结果?当然,我只想实现一次我的复杂方法。因此,我引入了可修改的参考参数,并根据某些条件,它们会被这些附加结果覆盖。

为了方便那些不需要额外结果的上下文,我引入了重载,这些重载创建传递给单个实现的虚拟变量。

请参阅以下简化的示例代码:

#include <iostream>
/**
* brief Checks whether everything is okay.
*
* param isCheckedFirstTime if point is not null, it will be overwritten with
* whether this method has been called for the first time
*
* returns okay or not
*/
bool isOkay(bool*& isCheckedFirstTime)
{
static bool isFirstTime = true;
if (nullptr != isCheckedFirstTime)
{
*isCheckedFirstTime = isFirstTime;
}
isFirstTime = false;
return true;
}
/**
* brief Checks whether everything is okay.
*
* returns okay or not
*/
bool isOkay()
{
bool* dummy = nullptr;
return isOkay(dummy);
}
int main()
{
const bool okay = isOkay();
std::cout << "Is everything okay?: " << okay << std::endl;
return 0;
}

显然,我可以通过为参数添加默认值来摆脱很多样板代码isCheckedFirstTime

如下所示
bool isOkay(bool*& isCheckedFirstTime = nullptr)

这是不合法的,因为我无法将非常量左值引用绑定到相应类型的右值。

有解决方法吗?或者是否有另一种可能性,只有一种方法执行所有计算,而不会对不同的输出进行重载,也不必在调用代码中声明虚拟参数?

我能想到的一种解决方案是将所有可能的结果打包到一个std::tuple中。然后调用方可以使用他想要的东西。但是,如果可选结果的计算成本很高,则它可能有一个缺点。然后有一个条件(如nullptr != ...)可以节省计算时间,如果没有人需要结果。

我期待您的建议!

通常这是通过返回std::tuple来完成的。

在您的情况下,它将看起来像这样:

std::tuple<bool,bool> isOkay()
{
static bool isFirstTime = true;
bool isCheckedFirstTime = isFirstTime;
isFirstTime = false;
return std::make_tuple(true, isCheckedFirstTime);
}

如果您需要返回可选的复杂对象或不想计算不需要的值,如果可以使用 C++17,最好使用std::optional

std::tuple<bool,std::optional<bool>> isOkay(bool needCheckFirstTime = false)
{
static bool isFirstTime = true;
std::optional<bool> isCheckedFirstTime;
if (needCheckFirstTime) {
isCheckedFirstTime = isFirstTime;
}
isFirstTime = false;
return std::make_tuple(true, isCheckedFirstTime);
}
因此,

我引入了可修改的参考参数,并根据某些条件,它们会被这些附加结果覆盖。

应该像瘟疫一样避免参数。如果函数生成结果,则它应该是其返回类型的一部分。那么我们如何为您的案件找出这种类型呢?

您已经建议了一个元组;在这种情况下,struct或元组会很好用。

但是,如果可选结果的计算成本很高,则它可能有一个缺点。

当然,但没有什么说你必须将论点与结果联系起来。函数可以采用位集或类似的枚举,告诉它确切地要计算什么,并返回一个充满optional值的结构。具体将在很大程度上取决于要解决的具体案件。

您似乎不确定isCheckedFirstTime应该是指针还是引用,因此您同时将其设为了指针。那只是不方便。

这可能更具表现力:

bool isOkay(std::optional<bool>& isCheckedFirstTime)
{
static bool isFirstTime = true;
if (isCheckedFirstTime)
{
*isCheckedFirstTime = isFirstTime;
}
isFirstTime = false;
return true;
}
bool isOkay()
{
std::optional<bool> dummy;
return isOkay(dummy);
}