首页 > 解决方案 > C++ 中的模板化 is_in() 函数(检查数组是否包含字符串)

问题描述

我想做以下事情:

std::string b = "b";
is_in("a", { "a", "b", "c" });
is_in("d", { "a", "b", "c" });
is_in(b, { "a", "b", "c" }); // fails
is_in(b, std::array{ "a", "b", "c" });

使用模板

template<typename Element, typename Container>
bool is_in(const Element& e, const Container& c)
{
    // https://stackoverflow.com/questions/20303821/how-to-check-if-string-is-in-array-of-strings
    return std::find(std::begin(c), std::end(c), e) != std::end(c);
}

template<typename Element>
bool is_in(Element e, std::initializer_list<Element> l)
{
    // return std::find(std::begin(l), std::end(l), e) != std::end(l);
    return is_in<Element, std::initializer_list<Element>>(e, l);
}

但我收到以下错误(使用 GCC 9.3.0):

no matching function for call to ‘is_in(std::string&, <brace-enclosed initializer list>)’

那里有任何大脑模板的家伙有建议吗?

标签: c++arraysstringtemplatesgcc

解决方案


对于is_in(b, { "a", "b", "c" });, 模板形参Element推导为std::string第一个参数b,推导为const char*第二个参数{ "a", "b", "c" };他们不匹配。

您可以为 提供两个模板参数is_in,例如

template<typename E1, typename E2>
bool is_in(E1 e, std::initializer_list<E2> l)
{
    // return std::find(std::begin(l), std::end(l), e) != std::end(l);
    return is_in<E1, std::initializer_list<E2>>(e, l);
}

或者使用std::type_identity(从 C++20 开始;并且很容易为 C++20 之前的版本编写一个)从类型推导中排除第二个函数参数。

template<typename Element>
bool is_in(Element e, std::initializer_list<std::type_identity_t<Element>> l)
{
    // return std::find(std::begin(l), std::end(l), e) != std::end(l);
    return is_in<Element, std::initializer_list<Element>>(e, l);
}

推荐阅读