C++ Check if one of multple values lower than int [duplicate] - c++

A few times in my program, I've had to check if a variable was one of many options. For example
if (num = (<1 or 2 or 3>)) { DO STUFF }
I've messed around with 'OR's, but nothing seems to be right. I've tried
if (num == (1 || 2 || 3))
but it does nothing.
I'd like to conveniently distinguish between several groups. For example
if (num = (1,2,3))
else if (num = (4,5,6))
else if (num = (7,8,9))

Here's a way in C++11, using 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);
}
with that, you can do:
if (is_in(num, {1, 2, 3})) { DO STUFF }
It is not very efficient though when not used with built-in types. int will work fine, but if you compare std::string variables for example, the produced code is just awful.
In C++17 however, you can instead use a much more efficient solution that works well with any type:
template<typename First, typename ... T>
bool is_in(First &&first, T && ... t)
{
return ((first == t) || ...);
}
// ...
// s1, s2, s3, s4 are strings.
if (is_in(s1, s2, s3, s4)) // ...
The C++11 version would be very inefficient here, while this version should produce the same code as hand-written comparisons.

If the values you want to check are sufficiently small, you could create a bit mask of the values that you seek and then check for that bit to be set.
Suppose, you care about a couple of groups.
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
}
This approach works best for values that don't exceed the natural size your CPU likes to work with. This would typically be 64 in modern times, but may vary depending upon the specifics of your environment.

You have to do the comparison with each value. E.g.
if (num == 1 || num == 2 || num == 3) { stuff }
You may also want to consider a switch and intentionally falling through cases (although I don't think it's the best solution for what you're stating).
switch (num) {
case 1:
case 2:
case 3:
{DO STUFF}
break;
default:
//do nothing.
}

I just had a similar problem and I came to these C++11 solutions:
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};
}
Or as alternative without the recursion terminating method. Be aware that here the order of comparisons is undefined and that this does not terminate early if the first match is found. But the code is more compact.
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};
}
So for both solutions the code would look like:
if (is(num).in(1,2,3)) {
// do whatever needs to be done
}

You can define a set of integers, add the desired values to it, and then use the find method to see if the value in question is in the set
std::set<int> values;
// add the desired values to your set...
if (values.find(target) != values.end())
...

I needed to do something similar for enums. I have a variable and wish to test it against a ranges of values.
Here I've used a variadic template function. Note the specialisation for const char* type, so that is_in( my_str, "a", "b", "c") has the expected outcome for when my_str stores "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...);
}
Example usage:
enum class day
{
mon, tues, wed, thur, fri, sat, sun
};
bool is_weekend(day d)
{
return is_in(d, day::sat, day::sun);
}

float n;
if (n<1) exit(0);
if (n / 3 <= 1)
// within 1, 2, 3
else if (n / 3 <= 2)
// within 4, 5, 6
else if (n / 3 <= 3)
// within 7, 8, 9

Related

If statement isn't checking stored input [duplicate]

A few times in my program, I've had to check if a variable was one of many options. For example
if (num = (<1 or 2 or 3>)) { DO STUFF }
I've messed around with 'OR's, but nothing seems to be right. I've tried
if (num == (1 || 2 || 3))
but it does nothing.
I'd like to conveniently distinguish between several groups. For example
if (num = (1,2,3))
else if (num = (4,5,6))
else if (num = (7,8,9))
Here's a way in C++11, using 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);
}
with that, you can do:
if (is_in(num, {1, 2, 3})) { DO STUFF }
It is not very efficient though when not used with built-in types. int will work fine, but if you compare std::string variables for example, the produced code is just awful.
In C++17 however, you can instead use a much more efficient solution that works well with any type:
template<typename First, typename ... T>
bool is_in(First &&first, T && ... t)
{
return ((first == t) || ...);
}
// ...
// s1, s2, s3, s4 are strings.
if (is_in(s1, s2, s3, s4)) // ...
The C++11 version would be very inefficient here, while this version should produce the same code as hand-written comparisons.
If the values you want to check are sufficiently small, you could create a bit mask of the values that you seek and then check for that bit to be set.
Suppose, you care about a couple of groups.
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
}
This approach works best for values that don't exceed the natural size your CPU likes to work with. This would typically be 64 in modern times, but may vary depending upon the specifics of your environment.
You have to do the comparison with each value. E.g.
if (num == 1 || num == 2 || num == 3) { stuff }
You may also want to consider a switch and intentionally falling through cases (although I don't think it's the best solution for what you're stating).
switch (num) {
case 1:
case 2:
case 3:
{DO STUFF}
break;
default:
//do nothing.
}
I just had a similar problem and I came to these C++11 solutions:
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};
}
Or as alternative without the recursion terminating method. Be aware that here the order of comparisons is undefined and that this does not terminate early if the first match is found. But the code is more compact.
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};
}
So for both solutions the code would look like:
if (is(num).in(1,2,3)) {
// do whatever needs to be done
}
You can define a set of integers, add the desired values to it, and then use the find method to see if the value in question is in the set
std::set<int> values;
// add the desired values to your set...
if (values.find(target) != values.end())
...
I needed to do something similar for enums. I have a variable and wish to test it against a ranges of values.
Here I've used a variadic template function. Note the specialisation for const char* type, so that is_in( my_str, "a", "b", "c") has the expected outcome for when my_str stores "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...);
}
Example usage:
enum class day
{
mon, tues, wed, thur, fri, sat, sun
};
bool is_weekend(day d)
{
return is_in(d, day::sat, day::sun);
}
float n;
if (n<1) exit(0);
if (n / 3 <= 1)
// within 1, 2, 3
else if (n / 3 <= 2)
// within 4, 5, 6
else if (n / 3 <= 3)
// within 7, 8, 9

how to tell if a enum class value is in a specified range of enum class in a more effective way? [duplicate]

A few times in my program, I've had to check if a variable was one of many options. For example
if (num = (<1 or 2 or 3>)) { DO STUFF }
I've messed around with 'OR's, but nothing seems to be right. I've tried
if (num == (1 || 2 || 3))
but it does nothing.
I'd like to conveniently distinguish between several groups. For example
if (num = (1,2,3))
else if (num = (4,5,6))
else if (num = (7,8,9))
Here's a way in C++11, using 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);
}
with that, you can do:
if (is_in(num, {1, 2, 3})) { DO STUFF }
It is not very efficient though when not used with built-in types. int will work fine, but if you compare std::string variables for example, the produced code is just awful.
In C++17 however, you can instead use a much more efficient solution that works well with any type:
template<typename First, typename ... T>
bool is_in(First &&first, T && ... t)
{
return ((first == t) || ...);
}
// ...
// s1, s2, s3, s4 are strings.
if (is_in(s1, s2, s3, s4)) // ...
The C++11 version would be very inefficient here, while this version should produce the same code as hand-written comparisons.
If the values you want to check are sufficiently small, you could create a bit mask of the values that you seek and then check for that bit to be set.
Suppose, you care about a couple of groups.
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
}
This approach works best for values that don't exceed the natural size your CPU likes to work with. This would typically be 64 in modern times, but may vary depending upon the specifics of your environment.
You have to do the comparison with each value. E.g.
if (num == 1 || num == 2 || num == 3) { stuff }
You may also want to consider a switch and intentionally falling through cases (although I don't think it's the best solution for what you're stating).
switch (num) {
case 1:
case 2:
case 3:
{DO STUFF}
break;
default:
//do nothing.
}
I just had a similar problem and I came to these C++11 solutions:
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};
}
Or as alternative without the recursion terminating method. Be aware that here the order of comparisons is undefined and that this does not terminate early if the first match is found. But the code is more compact.
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};
}
So for both solutions the code would look like:
if (is(num).in(1,2,3)) {
// do whatever needs to be done
}
You can define a set of integers, add the desired values to it, and then use the find method to see if the value in question is in the set
std::set<int> values;
// add the desired values to your set...
if (values.find(target) != values.end())
...
I needed to do something similar for enums. I have a variable and wish to test it against a ranges of values.
Here I've used a variadic template function. Note the specialisation for const char* type, so that is_in( my_str, "a", "b", "c") has the expected outcome for when my_str stores "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...);
}
Example usage:
enum class day
{
mon, tues, wed, thur, fri, sat, sun
};
bool is_weekend(day d)
{
return is_in(d, day::sat, day::sun);
}
float n;
if (n<1) exit(0);
if (n / 3 <= 1)
// within 1, 2, 3
else if (n / 3 <= 2)
// within 4, 5, 6
else if (n / 3 <= 3)
// within 7, 8, 9

Can this code that expands integer parameter pack be written with just 1 function?

I have code that uses fold expressions to compare function argument against integer parmeters of class template.
Code works AFAIK, but I wonder if it is possible to do what I want without _impl helper function.
Full code(my question is if contains can be implemented without contains_impl):
#include <algorithm>
#include <iostream>
#include <utility>
#include <cstdlib>
#include <tuple>
template <int H, int... T>
class if_set {
private:
template<typename... Ts>
bool contains_impl(const int& val, Ts... ts) const{
return (false || ... || (val == ts));
}
public:
bool contains(const int& val) const {
return contains_impl( val, H, T...);
}
};
using namespace std;
int main()
{
constexpr if_set<1,3,4,5> isi;
for (int i = -1; i < 10; ++i) {
cout << i << ": " << boolalpha << isi.contains(i) << endl;
}
if_set<'a','e','i','o','u', 'A', 'E', 'I', 'O', 'U'> vowels;
string word = "ARCADE FIRE: Modern man";
cout << word << endl;
word.erase(remove_if(word.begin(), word.end(), [&vowels](const char& c){return vowels.contains (c);}), word.end());
cout << word << endl;
}
Note 1: I know this code has many issues, I do not plan to use it in production and I discourage people from using it directly or as inspiration, this is a toy example I wanted to implement after reading interesting article about frozen C++ library.
Note 2: false || looks ugly, but IDK any nicer way.
Yes, you can do it:
template <int H, int... T>
class if_set {
public:
bool contains(const int& val) const {
return ((val == H) || ... || (val == T));
}
};
Alternatively, you could just work on std::integer_sequences:
template<typename T1, typename T2, T1... Is>
bool contains(std::integer_sequence<T1, Is...>, T2 val) {
return (... || (val == Is)); // perhaps should be (false || ... || (val == Is)), but this appears to work
}

What is the most efficient way to add arbitrary number of elements to an std::vector in C++?

I have a defined class A and an std::vector vec that stores a series of A instances. I attempt to write a function that appends an arbitrary number of A instances to vec.
Should I use vec.reserve() along with vec.push_back() since constantly resizing vector is expensive? Or, should I use vec.insert()?
Currently, I'm not sure if I should design the function to accept a variable number of arguments using variadic functions or a vector of A instances that I'd like to combine and then concatenate with vec?
What is an efficient way to design this function (speed is critical and A is a complex class)?
The following should cover common cases, I think. The rref_capture trick is from this answer. The point of it all is that the values are moved whenever possible.
You can also use a variadic template version, as given in the other answer.
// https://github.com/KubaO/stackoverflown/tree/master/questions/vector-append-40274282
#include <array>
#include <cassert>
#include <initializer_list>
#include <iterator>
#include <type_traits>
#include <vector>
template<typename T>
class rref_capture {
T* ptr;
public:
rref_capture(T&& x) : ptr(&x) {}
operator T&& () const { return std::move(*ptr); } // restitute rvalue ref
};
template <typename T>
void append(std::vector<T> & v,
typename std::decay<std::initializer_list<rref_capture<T>>>::type u) {
v.reserve(v.size() + u.size());
for (auto && item : u)
v.push_back(std::move(item));
}
template <typename T, typename U>
void append(std::vector<T> & v, U && u) {
v.reserve(v.size() + std::distance(std::begin(u), std::end(u)));
for (auto & item : u)
v.push_back(std::move(item));
}
template <typename T, typename U>
void append(std::vector<T> & v, U & u) {
v.reserve(v.size() + std::distance(std::begin(u), std::end(u)));
for (auto & item : u)
v.push_back(item);
}
struct A {
static int copies, moves;
A() {}
A(A&&) { moves++; }
A(const A&) { copies++; }
A& operator=(const A&) { copies++; return *this; }
static void reset() { A::copies = 0; A::moves = 0; }
};
int A::copies, A::moves;
int main() {
std::vector<A> vec;
vec.reserve(100);
A::reset();
append(vec, {A(), A()});
assert(A::copies == 0 && A::moves == 2 && vec.size() == 2);
auto vec2 = vec;
A::reset();
append(vec, vec2);
assert(A::copies == 2 && A::moves == 0 && vec.size() == 4);
A::reset();
append(vec, std::move(vec2));
assert(A::copies == 0 && A::moves == 2 && vec.size() == 6);
A::reset();
append(vec, std::array<A,2>{A(), A()});
assert(A::copies == 0 && A::moves == 2 && vec.size() == 8);
const std::vector<A> cvec{2};
A::reset();
append(vec, cvec);
assert(A::copies == 2 && A::moves == 0 && vec.size() == 10);
A arr[2];
A::reset();
append(vec, arr);
assert(A::copies == 2 && A::moves == 0 && vec.size() == 12);
}
Well... I suppose you could use reserve() one time and then add the single element using push_back().
The following example use int instead of class A but should give the idea
#include <vector>
#include <iostream>
template <typename T>
void appendT (std::vector<T> & v)
{ }
template <typename T, typename ... Ts>
void appendT (std::vector<T> & v, T t, Ts ... ts)
{
v.push_back(t);
appendT(v, ts...);
}
template <typename T, typename ... Ts>
void appendTs (std::vector<T> & v, Ts ... ts)
{
v.reserve(v.size() + sizeof...(Ts));
appendT(v, ts...);
}
int main()
{
std::vector<int> v { 2, 3, 5 };
appendTs(v, 7, 11, 13, 17);
for ( auto const & i : v )
std::cout << ' ' << i; // print " 2 3 5 7 11 13 17"
std::cout << std::endl;
}
If you don't like the recursive solution, you can write an appendTs() that do all the works (but I don't know how to avoid the annoing "warning: unused variable 'unused'" I know how to avoid the warning but I don't know if it's a good idea Kuba Ober suggested me an elegant way to avoid the warning)
#include <vector>
#include <iostream>
template <typename T, typename ... Ts>
void appendTs (std::vector<T> & v, Ts ... ts)
{
v.reserve(v.size() + sizeof...(Ts));
// the first '0' is to avoid an error when sizeof...(Ts) is zero
char unused[] { '0', (v.push_back(ts), '0')... };
// the following statement is to avoid an annoing "unused variable
// 'unused'" warning (thanks Kuba Ober)
(void)unused;
}
int main()
{
std::vector<int> v { 2, 3, 5 };
appendTs(v, 7, 11, 13, 17);
for ( auto const & i : v )
std::cout << ' ' << i; // print " 2 3 5 7 11 13 17"
std::cout << std::endl;
}

Shorthand for checking for equality to multiple possibilities [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++ comparing bunch of values with a given one
I'm needing to check for equality in a for loop in C++, however the loop needs to work for x equaling multiple possibilities.
For example, right now I have something similar to:
if(x==a || x==b || x==c || x==d || x==e || x==f || x==g || x==h)
{
//loop body
}
But with the number I have, it looks messy and I was wondering if there was a shorthand way of saying "if (x == (any of these))" or if writing them all out was the only option.
Thanks!
Thank you for your question, now as I found a solution (and an elegant one I dare say), I'll use it myself.
Unlike solutions with std::find : Will a ) be unrolled to N comparisons in compile time b) work with any types which X can be compared to
struct TagAnyOf {};
template <typename... Args>
std::tuple <TagAnyOf, Args...> AnyOf (Args&&... args)
{
return std::tuple <TagAnyOf, Args...> (TagAnyOf(), std::forward<Args>(args)...);
}
template <class X, class Tuple, size_t Index, size_t ReverseIndex>
struct CompareToTuple
{
static bool compare (const X& x, const Tuple& tuple)
{
return x == std::get<Index> (tuple) || CompareToTuple<X, Tuple, Index+1, ReverseIndex-1>::compare (x, tuple);
}
};
template <class X, class Tuple, size_t Index>
struct CompareToTuple <X, Tuple, Index, 0>
{
static bool compare (const X& x, const Tuple& tuple)
{
return false;
}
};
template <typename X, typename... Args>
bool operator == (const X& x, const std::tuple<TagAnyOf, Args...>& any)
{
typedef std::tuple <TagAnyOf, Args...> any_of_type;
return CompareToTuple <X, any_of_type, 1, std::tuple_size<any_of_type>::value-1>::compare (x, any);
}
Usage
int main()
{
int x = 1;
if (x == AnyOf (1, 2, 3, 4))
{
std::cout << "Yes!" << std::endl;
}
else
{
std::cout << "No!" << std::endl;
}
if (x == AnyOf (4, 3, 2, 1))
{
std::cout << "Yes!" << std::endl;
}
else
{
std::cout << "No!" << std::endl;
}
if (x == AnyOf (2, 3, 4, 5))
{
std::cout << "Yes!" << std::endl;
}
else
{
std::cout << "No!" << std::endl;
}
return 0;
}
Consider using a function that takes an initializer_list (this is a c++11 feature).
the first parameter would be the left hand value(x in your case), and the rest of the parameters will be right hand values.
Here is an example that accomplishes the task using templates.
#include <iostream>
#include <cstdlib>
#include <algorithm>
template<class T>
bool Test(T const& test, std::initializer_list<T> const& values){
return std::find(std::begin(values), std::end(values), test) != std::end(values);
}
int main(){
char var1 = 'a';
char var2 = 'a';
char var3 = 'b';
char var4 = 'c';
char var5 = 'd';
if (Test<char>(var1,{var2,var3,var4,'o',var5})){
std::cout << "true. at least one is equivelent" << std::endl;
}else{
std::cout << "false. none are equivelent" << std::endl;
}
if (Test<char>(var1,{var3,var4,var5})){
std::cout << "true. at least one is equivelent" << std::endl;
}else{
std::cout << "false. none are equivelent" << std::endl;
}
return EXIT_SUCCESS;
}
If you are doing this with classes, make sure you overload the '!=' operator.
edit: mistake fixed. pointed out by GManNickG
I was wondering if there was a shorthand way of saying "if (x == (any
of these))"
Yes, the standard gives you std::find and std::find_if to answer exactly this question:
int a=3,b=5,c=6,d=7;
std::array<int,4> vals{{a,b,c,d}}; // or std::vector
int x=5;
bool foundit= (end(vals) != std::find_if(begin(vals), end(vals),x );
You will need
#include <array>
#include <algorithm>
You can also use std::initializer_list<int> booleans{a,b,c,d}; instead of vector or array
If your conditions where more complicated, you could use find_if:
bool foundit= (end(vals) !=
std::find_if(begin(vals), end(vals),
[&x](const int &v){return v*(v+x)<x;}));