检查元素是否在 std::initializer_list 中
Check whether an element is in std::initializer_list
我希望能够用类似于以下Python代码编写C++:
if x in [1, 2, 3, 5] ...
测试元素是否包含在就地定义的一组硬编码值中。喜欢这个:
if (in(x, {1, 2, 3, 5})) ...
以下是 in
函数的可能实现:
template<class T>
bool in(const T& x, std::initializer_list<T> c)
{
return std::find(c.begin(), c.end(), x) != c.end();
}
我的问题是:我真的必须自己编写这个函数吗?那里是否有任何默认实现?也许在提升?我检查了boost::contains
,但它仅适用于字符串。
> 如果你可以访问 c++20,你可以使用 set
的 contains
它返回一个bool
,允许你执行以下操作:
if(set{ 4, 8, 15, 16, 23, 42 }.contains(x))
现场示例
否则,仅使用 c++11,您仍然可以使用 set
的 count
,它只返回 1 或 0,允许您执行以下操作:
if(set<int>{ 4, 8, 15, 16, 23, 42 }.count(x) > 0U)
现场示例
请记住,幻数可能会让您的观众感到困惑(并导致 5 季的迷失。
我建议将您的数字声明为const initializer_list<int>
并给它们一个有意义的名称:
const auto finalCandidates{ 4, 8, 15, 16, 23, 42 };
if(cend(finalCandidates) != find(cbegin(finalCandidates), cend(finalCandidates), x))
boost::algorithm::contains
不仅适用于字符串,也适用于任何范围,即可以产生开始和结束迭代器的序列。要查找单个值,请按如下方式使用它:
auto l = {1,2,3,4};
auto l1 = {2}; // thing you want to find
if(boost::algorithm::contains(l, l1)) { ... }
您只能使用标准库执行搜索,但这样做会更加冗长。有几个选项是:
使用λ
if(std::any_of(l.begin(), l.end(), [](int i){ return i == 2; })) { ... }
使用
std::bind
using std::placeholders::_1; if(std::any_of(l.begin(), l.end(), std::bind(std::equal_to<>(), 2, _1)) { ... }
现场演示
请注意,std::equal_to<>()
是仅限 C++14 的选项。对于 C++11 编译器,请使用 std::equal_to<int>()
。
事实上,STL没有一个简单的std::contains()
函数。最近,在reddit上有一个关于这个话题的讨论。
不幸的是,由此得出的结果是 拥有std::contains()
被认为是有害的,因为它鼓励人们编写缓慢的算法。以
if (!std::contains(my_set.begin(), my_set.end(), entry)) {
my_set.insert(entry);
}
此代码示例实质上搜索正确位置两次:一次在包含中,一次查找插入位置。
在我看来,拥有std::contains()
仍然会很有帮助,但到目前为止还没有人被说服写提案。
因此,要么使用 boost(如此线程中的其他人所建议的那样),要么编写您自己的函数,您基本上已经这样做了:-)
- 使用std::multimap迭代器创建std::list
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- 如何在 C 中正确使用 libiconv 使其不会报告"Arg list too long"?
- C++中带有List类的迭代器Segfault
- 使用"std::unordereded_map"映射到"std::list"对象
- GCC对可能有效的代码抛出init list生存期警告
- 使用std::list创建循环链表
- C2664 无法从'initializer list'转换参数
- 使用 std::min "no matching function for call to ‘min(<brace-enclosed initializer list>)’"时出错
- 在C++中标记化"Braced Initializer List"样式字符串(使用 Boost?
- "默认参数":无法从'initializer list'转换为'std::initializer_list'
- 无法从'initializer-list'转换为用户控制器
- 如何修复<function-style-cast>错误:无法从'initializer list'转换为asdending比较<W>(模板函子)
- 递归调用中出现错误"[Error] expression list treated as compound expression in initializer [-fpermissive]"
- VS2015无法从'initializer list'转换为'std::string'错误
- 编译器错误:"Non-aggregates cannot be initialized with initializer list."
- 无法转换...从 '<brace-enclosed initializer list>' 到 地图
- 无法将'<brace-enclosed initializer list>'转换为'double'作为回报
- <function-style-cast> 错误:无法从'initializer list'转换为'std::thread'
- initializer语言 - list不能转换为const margin *