Еще один способ сделать это:
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
using namespace std;
template <typename T>
string join(const T& v, const string& delim) {
ostringstream s;
for (const auto& i : v) {
if (&i != &v[0]) {
s << delim;
}
s << i;
}
return s.str();
}
int main() {
cout << join(vector<int>({1, 2, 3, 4, 5}), ",") << endl;
}
(c ++ 11 для цикла и «авто»)
Если значения, которые вы хотите проверить, достаточно малы, вы можете создать битную маску для значений, которые вы ищете, а затем проверить, чтобы этот бит был установлен.
Предположим, вы заботитесь о паре групп.
static const unsigned values_group_1 = (1 << 1) | (1 << 2) | (1 << 3);
static const unsigned values_group_2 = (1 << 4) | (1 << 5) | (1 << 6);
static const unsigned values_group_3 = (1 << 7) | (1 << 8) | (1 << 9);
if ((1 << value_to_check) & values_group_1) {
// You found a match for group 1
}
if ((1 << value_to_check) & values_group_2) {
// You found a match for group 2
}
if ((1 << value_to_check) & values_group_3) {
// You found a match for group 3
}
Этот подход лучше всего подходит для значений, которые не превышают естественный размер, с которым вам нравится работать процессор. Обычно это будет 64 в наше время, но может варьироваться в зависимости от специфики вашей среды.
Мне нужно было сделать что-то подобное для перечислений. Я имею переменную и хочу ее протестировать против диапазонов значений.
Здесь я использовал вариационную функцию шаблона. Обратите внимание на специализацию для типа const char*
, так что is_in( my_str, "a", "b", "c")
имеет ожидаемый результат, когда my_str
сохраняет "a"
.
#include <cstring>
template<typename T>
constexpr bool is_in(T t, T v) {
return t == v;
}
template<>
constexpr bool is_in(const char* t, const char* v) {
return std::strcmp(t,v);
}
template<typename T, typename... Args>
constexpr bool is_in(T t, T v, Args... args) {
return t==v || is_in(t,args...);
}
Пример использования:
enum class day
{
mon, tues, wed, thur, fri, sat, sun
};
bool is_weekend(day d)
{
return is_in(d, day::sat, day::sun);
}
Вы можете определить набор целых чисел, добавить к нему нужные значения, а затем использовать метод find, чтобы узнать, находится ли заданное значение в наборе
std::set<int> values;
// add the desired values to your set...
if (values.find(target) != values.end())
...
count
вместо set
.
– user
27 June 2014 в 21:46
if (std::set<int>({1, 2, 3}).count(target)) {
...
– Chris Dodd
4 August 2018 в 07:30
У меня была аналогичная проблема, и я пришел к этим решениям на C ++ 11:
template <class T>
struct Is
{
T d_;
bool in(T a) {
return a == d_;
}
template <class Arg, class... Args>
bool in(Arg a, Args... args) {
return in(a) || in(args...);
}
};
template <class T>
Is<T> is(T d) {
return Is<T>{d};
}
Или как альтернатива без метода завершения рекурсии. Имейте в виду, что здесь порядок сравнений не определен и что это не заканчивается раньше, если найдено первое совпадение. Но код более компактен.
template <class T>
struct Is {
const T d_;
template <class... Args>
bool in(Args... args) {
bool r{ false };
[&r](...){}(( (r = r || d_ == args), 1)...);
return r;
}
};
template <class T>
Is<T> is(T d) {
return Is<T>{d};
}
Итак, для обоих решений код будет выглядеть так:
if (is(num).in(1,2,3)) {
// do whatever needs to be done
}
Вы должны выполнить сравнение с каждым значением. Например,
if (num == 1 || num == 2 || num == 3) { stuff }
Вы также можете рассмотреть возможность переключения и намеренно проваливаться в случаях (хотя я не думаю, что это лучшее решение для того, что вы заявляете).
switch (num) {
case 1:
case 2:
case 3:
{DO STUFF}
break;
default:
//do nothing.
}
Вот в C ++ 11, используя std::initializer_list
:
#include <algorithm>
#include <initializer_list>
template <typename T>
bool is_in(const T& v, std::initializer_list<T> lst)
{
return std::find(std::begin(lst), std::end(lst), v) != std::end(lst);
}
с этим, вы можете сделать:
if (is_in(num, {1, 2, 3})) { DO STUFF }