如何使函数的参数列表更清晰?

How to make the parameter list of a function cleaner?

在我最近观看的一段视频中,Kate Gregory 建议如果一个函数有一个巨大的参数列表(例如 4 个以上的参数),应该将所有这些参数放在 struct 中(即 make它们是结构的成员)并在初始化 struct 的实例后将其传递给所述函数(显然这也需要重构函数本身)。

我有一个带有 5 个参数的效用函数,您可以在下面看到:

bool convert_str_to_valid_ints( const std::string_view inputStr, const std::span<int> result_ints,
                                const std::size_t expectedTokenCount, const std::vector<int>& specificTokensIndices,
                                const std::pair<int, int> acceptableRange =
                                std::pair<int, int>( std::numeric_limits<int>::min( ), std::numeric_limits<int>::max( ) ) );

正如所料,在任何调用站点调用此函数都会引入大量可怕的代码!

上面可以变成这样:

// In a header file
struct ParameterList
{
    std::string_view inputStr;
    std::span<int> result_ints;
    std::size_t expectedTokenCount;
    std::vector<int> specificTokensIndices;
    std::pair<int, int> acceptableRange = std::pair<int, int>( std::numeric_limits<int>::min( ),
                                                               std::numeric_limits<int>::max( ) );
};

bool convert_str_to_valid_ints( const ParameterList& pl );
.
.
.
// in any source file that includes the said header file
const ParameterList pl { /* arguments go here */ };

bool isValid { convert_str_to_valid_ints( pl ) }; // much more readable, and possibly more performant?

我试图将它分解成更小的部分(例如,两个较小的函数,每个函数的参数都更少)但我没有这样做,因为这个函数的作用在逻辑上不能分解成两个部分,而且它不会很有意义。所以我想寻求帮助,看看 Gregory 的方法在这种特殊情况下是否是一个有效的选择。

现在如果有人说这是一个有效的选择,那么我应该把这个特殊用途的定义放在哪里 struct(我猜是在声明大函数的 header 里面,这样其他源文件可以通过包含大函数的 header 然后调用函数来访问该结构)?

该结构应该在一个头文件中,可能在它自己的头文件中。 你考虑过这个吗? 将convert函数添加到struct中,这样就可以直接使用参数,也方便以后复用。

#include <iostream>
#include <string_view>
#include <span>
#include <vector>

struct ParameterListConverter
{
    std::span<int> result_ints; // you can even set some reasonable defaults here
    std::size_t expectedTokenCount;
    std::vector<int> specificTokensIndices;
    std::pair<int, int> acceptableRange = std::pair<int, int>(std::numeric_limits<int>::min(),
    std::numeric_limits<int>::max());

    bool convert(const std::string input) const
    {
        // ... your convert function using the parameters set
    };
};


int main()
{
    ParameterListConverter converter
    {
        .expectedTokenCount = 42ul
    };

    bool success = converter.convert("123,234");

    return 1;
}