[英]Check whether an element is in std::initializer_list
I want to be able to write in C++ something similar to the following Python code:我希望能够用 C++ 编写类似于以下 Python 代码的内容:
if x in [1, 2, 3, 5] ...
to test whether an element is contained in a set of hard-coded values, defined in-place.测试元素是否包含在就地定义的一组硬编码值中。 Like this:
像这样:
if (in(x, {1, 2, 3, 5})) ...
Here is the possible implementation of the in
function:下面是
in
函数的可能实现:
template<class T>
bool in(const T& x, std::initializer_list<T> c)
{
return std::find(c.begin(), c.end(), x) != c.end();
}
My question is: do I really have to write this function by myself?我的问题是:我真的必须自己编写这个函数吗? Are there any default implementations over there?
那里有任何默认实现吗? Maybe in boost?
也许在提升? I checked
boost::contains
, but it works only with strings.我检查了
boost::contains
,但它只适用于字符串。
If you have access to c++20 you can use set
's contains
which returns a bool
allowing you to do:如果您可以访问c++20 ,则可以使用
set
的contains
,它返回一个bool
允许您执行以下操作:
if(set{ 4, 8, 15, 16, 23, 42 }.contains(x))
Otherwise, with just c++11 you can still use set
's count
which only returns 1 or 0 allowing you to do something like:否则,仅使用c++11,您仍然可以使用
set
的count
,它只返回 1 或 0,允许您执行以下操作:
if(set<int>{ 4, 8, 15, 16, 23, 42 }.count(x) > 0U)
Keep in mind that magic numbers can be confusing for your audience (and cause 5 seasons of Lost.)请记住,神奇数字可能会让您的观众感到困惑(并导致 5 季迷失。)
I'd recommend declaring your numbers as a const initializer_list<int>
and giving them a meaningful name:我建议将您的数字声明为
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
doesn't only work on strings, it works on any range , ie a sequence that can yield a begin and end iterator. boost::algorithm::contains
不仅适用于字符串,它还适用于任何范围,即可以产生开始和结束迭代器的序列。 To find a single value use it as follows:要查找单个值,请按如下方式使用它:
auto l = {1,2,3,4};
auto l1 = {2}; // thing you want to find
if(boost::algorithm::contains(l, l1)) { ... }
You can perform your search using the standard library only, but doing so is quite a bit more verbose.您只能使用标准库执行搜索,但这样做比较冗长。 A couple of options are:
几个选项是:
using a lambda使用 lambda
if(std::any_of(l.begin(), l.end(), [](int i){ return i == 2; })) { ... }
using std::bind
使用
std::bind
using std::placeholders::_1; if(std::any_of(l.begin(), l.end(), std::bind(std::equal_to<>(), 2, _1)) { ... }
Note that std::equal_to<>()
is a C++14-only option.请注意
std::equal_to<>()
是 C++14-only 选项。 For a C++11 compiler, use std::equal_to<int>()
.对于 C++11 编译器,使用
std::equal_to<int>()
。
Indeed the STL does not have a simple std::contains()
function.实际上,STL 没有简单的
std::contains()
函数。 Recently, there was a discussion on reddit about this topic.最近, reddit 上有一个关于这个话题的讨论。
Unfortunately, what came out of this is that it is considered harmful to have std::contains()
, since it encourages people to write slow algorithms.不幸的是,结果是
std::contains()
被认为是有害的,因为它鼓励人们编写缓慢的算法。 Think for instance of想想例如
if (!std::contains(my_set.begin(), my_set.end(), entry)) {
my_set.insert(entry);
}
This code example essentially searches for the correct position twice: Once in contains, and once to find the insert location.此代码示例本质上会搜索正确的位置两次:一次是在 contains 中,一次是为了找到插入位置。
In my opinion, it would still be very helpful to have std::contains()
, but so far no one was convinced yet to write a proposal.在我看来,拥有
std::contains()
仍然非常有帮助,但到目前为止还没有人相信要写一份提案。
So either use boost (as suggested by other in this thread), or write your own function which you essentially already did :-)因此,要么使用 boost(如本线程中的其他人所建议的那样),要么编写您自己的函数,您基本上已经这样做了:-)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.