我想做以下事情:
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>)’
有沒有大腦模板的家伙有建議?
uj5u.com熱心網友回復:
對于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 開始;并且很容易為 pre-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);
}
uj5u.com熱心網友回復:
另一種方法是在比較它們之前將不匹配的字串型別轉換為 std::string。
#include <cassert>
#include <array>
#include <string>
// Help the compiler figure out to compare "unrelated" string types
namespace details
{
template<typename type_t>
struct compare_as
{
using type = type_t;
};
template<std::size_t N>
struct compare_as<char[N]>
{
using type = std::string;
};
template<>
struct compare_as<char*>
{
using type = std::string;
};
}
// template for "array" style parameters
template<typename type_t, typename coll_t, std::size_t N>
constexpr auto is_in(const type_t& value, const coll_t(&values)[N])
{
for (const auto& v : values)
{
typename details::compare_as<coll_t>::type lhs{ v };
typename details::compare_as<type_t>::type rhs{ value };
if (lhs == rhs) return true;
}
return false;
}
// template for containers
template<typename type_t, typename coll_t>
constexpr auto is_in(const type_t& value, const coll_t& values)
{
for (const auto& v : values)
{
typename details::compare_as<type_t>::type lhs{ v };
typename details::compare_as<type_t>::type rhs{ value };
if (lhs == rhs) return true;
}
return false;
}
int main()
{
// for non-string types compile time checking is possible
static_assert(is_in(1, { 1,2,3 }));
std::string b = "b";
assert(is_in("a", { "a", "b", "c" }));
assert(!is_in("d", { "a", "b", "c" }));
assert(is_in(b, { "a", "b", "c" }));
assert(is_in(b, std::array{ "a", "b", "c" }));
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/315944.html
上一篇:C#旋轉陣列遞回(左,右)多次
