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

时间:2019-07-19 08:03:20

标签: c++

我正在尝试改善代码风格。

有时,我有一些方法可以执行复杂的检查或计算,并且根据调用方法的上下文,我需要与这些算法不同的结果。假设有一个结果,它总是需要的,它将是方法的返回值。但是如何处理可选的其他结果呢?当然,我只想实现我的复杂方法一次。因此,我介绍了可修改的参考参数,并根据某些条件将其替换为这些附加结果。

为方便我不需要其他结果的环境,我引入了重载,这些重载创建了将传递给单个实现的虚拟变量。

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

#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 != ...)可以节省计算时间。

我期待着您的建议!

3 个答案:

答案 0 :(得分:2)

通常,这是通过返回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);
}

答案 1 :(得分:1)

您似乎不确定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);
}

答案 2 :(得分:1)

  

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

避免像瘟疫一样使用掉参数。如果函数产生结果,则它应该是其返回类型的一部分。那么我们如何找出适合您情况的类型?

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

  

但是,如果计算可选结果的成本很高,则可能会有不利之处。

当然可以,但是没有任何内容表明您必须将参数绑定到结果上。函数可以使用一个位集或类似的枚举,告诉其确切要计算什么,并返回一个充满optional值的结构。具体情况将在很大程度上取决于要解决的具体情况。