如何缩短此方法签名?

时间:2018-08-15 06:26:41

标签: c++ c++11

我有以下带有方法签名的类,如下所示:

class Foo
{
    public:
        std::vector<std::string> barResults(const std::vector<std::string>&, const std::vector<std::string>&);
}

在实现文件中,我已经知道了:

std::vector<std::string> Foo::barResults(const std::vector<std::string>& list1, const std::vector<std::string>& list2)
{
    std::vector<std::string> results;
    // small amount of implementation here...
    return results;
}

所以我心想,让我看看是否可以通过一些自动魔术来简化此函数签名,因为它已经变成了“满满的行”!所以我尝试了这个...

class Foo
{
    public:
        auto barResults(const std::vector<std::string>&, const std::vector<std::string>&);
}

auto Foo::barResults(const std::vector<std::string>& list1, const std::vector<std::string>& list2)
{
    std::vector<std::string> results;
    // small amount of implementation here...
    return results;
}

现在忽略了这样一个事实,是的,我可以使用“ using namespace std”对其进行大量裁剪,我想知道为什么编译器给我一个错误“ ”,该函数不能返回“ auto”在定义之前使用”。

我个人认为编译器可以轻松推断出该方法的返回类型,但在这种情况下似乎并非如此。当然,您可以使用尾随返回类型来修复它,如下所示:

class Foo
{
    public:
        std::vector<std::string> barResults(const std::vector<std::string>&, const std::vector<std::string>&) -> std::vector<std::string>;
}

但是,如果您使用上面的方法,它并没有比以前更好。因此,除了“使用命名空间std”之外,还有一种更好的方法可以执行上述操作,为什么在这种情况下编译器不能推断出return类型?甚至,这是否取决于此方法的调用方式导致编译器无法弄清楚返回类型。

3 个答案:

答案 0 :(得分:5)

这里的问题是包含文件如何工作的问题。您的错误:

  

返回'auto'的函数在定义之前不能使用

表示您正在使用函数的文件中,函数的定义(即实现)在使用前不在文件中的任何位置。这意味着使用该函数编译代码的编译器无法推断出函数的返回类型,因为这需要访问定义(实现)。造成这种情况的最可能原因是该函数的定义(实现)位于其自己的源文件(.cpp,.c等)中,未包含在内。为了更全面地理解这一点,我建议您阅读this的答案,也许也阅读this的答案。


要解决名义上的问题,缩短该签名的最简单方法可能是使用typedef。更具体地说,您可以在适当的地方添加以下代码,前提是范围合适(我将其添加为您班级的公共成员):

typedef std::vector<std::string> strvec;

这使您可以更容易管理地重写方法签名:

strvec barreuslts(const strvec&, const strvec&)

答案 1 :(得分:2)

当坚持使用C ++ 11时,您不能依赖推导的返回类型,而需要尾随的返回类型(尽管C ++ 14允许这样做)。由于在您的情况下,尾随返回类型没有什么特别之处,即没有传递decltype表达式来确定返回类型,因此我将尝试使用一些类型别名来缩短方法签名:

class Foo
{
    public:
        using StrVec = std::vector<std::string>;

        StrVec barResults(const StrVec&, const StrVec&);
};

Foo::StrVec Foo::barResults(const StrVec& list1, const StrVec& list2)
{
    StrVec results;
    // small amount of implementation here...
    return results;
}

答案 2 :(得分:2)

如果您只是在寻找一种视觉上吸引人的方式来处理较长的签名,请停止将所有内容强制放在同一行上。放宽您的垂直间距并插入换行符。签名包含呼叫者的质量信息,您可能需要的是多行签名。如果您使用80个字符的页面宽度,请重新考虑访问说明符上的缩进。

class Foo
{
public:
    std::vector<std::string> barResults(const std::vector<std::string>&,
                                        const std::vector<std::string>&);
}


std::vector<std::string>
Foo::barResults(const std::vector<std::string>& list1,
                const std::vector<std::string>& list2)
{
    std::vector<std::string> results;
    // small amount of implementation here...
    return results;
}

拆分声明时有很多样式。在您的工具集中拥有像clang-format这样的工具,将为您自动,一致地完成此操作。