在 C++ 中检查多个值是否相等

cxx*_*xxl 3 c++ templates

我正在 C++ 中寻找一种简单、快速和描述性的方法来检查一个值是否包含在一组固定的其他值中。就像在 Python 中一样,可以在其中编写

if some_function() in (2, 3, 5, 7, 11):
    do_something()
Run Code Online (Sandbox Code Playgroud)

一些明显的选择是:

  1. switch/ case:如果有问题的值是整数,那么可以这样写:

    switch (some_function()) {
        case 2: case 3: case 5: case 7: case 11: do_something();
    }
    
    Run Code Online (Sandbox Code Playgroud)

    不幸的是,这只适用于整数,我敢说它不是很漂亮。

  2. 使用局部变量保存临时结果:

    const auto x = some_function();
    if (x == 2 || x == 3 || x == 5 || x == 7 || x == 11) do_something();
    
    Run Code Online (Sandbox Code Playgroud)

    我想避免命名临时变量。此外,这编写起来很乏味并且容易出错。

  3. 使用std::set:这可以写成(至少在 C++20 中)为:

    if (std::set({ 2, 3, 5, 7, 11 }).contains(some_function())) do_something();
    
    Run Code Online (Sandbox Code Playgroud)

    这很好,但我担心它有一些沉重的 STL 开销。

还有其他更便宜的方法吗?也许一些可变参数模板解决方案?

cig*_*ien 8

是的,您确实可以编写一个可变参数模板函数,结合折叠表达式,如下所示:

namespace my 
{
  template<typename T, typename ... Vals>
  bool any_of(T t, Vals ...vals)
  {
     return (... || (t == vals));
  }
}  
Run Code Online (Sandbox Code Playgroud)

然后像这样使用它:

if (my::any_of(some_function(), 2, 3, 5, 7, 11))
{
    do_something();
}
Run Code Online (Sandbox Code Playgroud)

请注意,我已经放入any_of了一个命名空间,以避免与std::any_of完全不同的函数混淆。