6

我有一个函数来检查 a 是否std::string包含子字符串。我将字符串传递为std::string_view,这样就不会发生复制。

bool containsSubstr(std::string_view str, std::string_view substr)
{
    return str.find(substr) != std::string::npos;
}

我现在想创建一个函数,使用新的 C++17 折叠表达式来检查字符串是否包含多个子字符串。同样,我想通过std::string_views 传递它们。

我怎样才能做到这一点?

template<typename... Substrs>
bool containsAllSubstr(std::string_view str, Substrs... substrs)
{
    return  (containsSubstr(str, substrs) && ...);
}

据我所知,上面的版本会将子字符串作为它们进来的类型。所以 astd::string会被复制。如何将类型修复为std::string_view?就像是:

template<> // does not compile
bool containsAllSubstr(std::string_view str, std::string_view... substrs)
{
    return  (containsSubstr(str, substrs) && ...);
}
4

1 回答 1

10

您不能拥有特定类型的函数参数包。但这很好(一旦添加const&):

template <typename... Substrs>
bool containsAllSubstr(std::string_view str, Substrs const&... substrs)
{
    return  (containsSubstr(str, substrs) && ...);
}

这不会制作任何副本,并且如果您传入不可转换为string_view. 如果你想让它对 SFINAE 友好,可以添加一个条件:

template <typename... Substrs,
    std::enable_if_t<(std::is_convertible_v<Substrs const&, std::string_view> && ...), int> = 0>
bool containsAllSubstr(std::string_view str, Substrs const&... substrs)
{
    return  (containsSubstr(str, substrs) && ...);
}

或者,如果您愿意对语法稍作更改,则可以采用一个数组:

template <size_t N>
bool containsAllSubstr(std::string_view str, std::string_view (&substrs)[N]);

但是你实际上并没有立即拥有一个包。但是,你可以只写一个循环。或者,如果您根本不需要编译时大小:

bool containsAllSubstr(std::string_view str, std::initializer_list<std::string_view> substrs);
于 2018-03-19T13:08:28.740 回答