Is there any way to shorten the condition for this if
statement?
int x;
if (x != 3 && x != 8 && x != 87 && x != 9){
SomeStuff();
}
I'm thinking of something sort of like this:
if (x != 3, 8, 87, 9) {}
But I tried that and it doesn't work. Do I just have to write it all out the long way?
If you want to know if an integer is in a given set of integers, then use std::set
:
std::set<int> accept { 1, 4, 6, 8, 255, 42 };
int x = 1;
if (!accept.count(x))
{
// ...
}
Just for completeness, I'll offer up using a switch:
switch (x) {
case 1:
case 2:
case 37:
case 42:
break;
default:
SomeStuff();
break;
}
While this is pretty verbose, it only evaluates x
once (if it is an expression) and probably generates the most efficient code of any solution.
Here is my solution using variadic template. The runtime performance is as efficient as manually writing x != 3 && x != 8 && x != 87 && x != 9
.
template <class T, class U>
bool not_equal(const T& t, const U& u) {
return t != u;
}
template <class T, class U, class... Vs>
bool not_equal(const T& t, const U& u, const Vs&... vs) {
return t != u && not_equal(t, vs...);
}
int main() {
std::cout << not_equal( 3, 3, 8, 87, 9) << std::endl;
std::cout << not_equal( 8, 3, 8, 87, 9) << std::endl;
std::cout << not_equal(87, 3, 8, 87, 9) << std::endl;
std::cout << not_equal( 9, 3, 8, 87, 9) << std::endl;
std::cout << not_equal(10, 3, 8, 87, 9) << std::endl;
}
Since C++17, the implementation can be simplified with the help of fold expressions:
template <class T, class... Vs>
bool not_equal(const T& t, const Vs&... vs) {
return ((t != vs) && ...);
}
What about this:
#include <iostream>
#include <initializer_list>
#include <algorithm>
template <typename T>
bool in(const T t, const std::initializer_list<T> & l) {
return std::find(l.begin(), l.end(), t) != l.end();
}
int main() {
std::cout << !in(3, {3, 8, 87, 9}) << std::endl;
std::cout << !in(87, {3, 8, 87, 9}) << std::endl;
std::cout << !in(10, {3, 8, 87, 9}) << std::endl;
}
or overloading the operator!=
:
template<typename T>
bool operator!=(const T t, const std::vector<T> & l) {
return std::find(l.begin(), l.end(), t) == l.end();
}
int main() {
std::cout << ( 3!=std::vector<int>{ 3, 8, 87, 9}) << std::endl;
std::cout << ( 8!=std::vector<int>{ 3, 8, 87, 9}) << std::endl;
std::cout << (10!=std::vector<int>{ 3, 8, 87, 9}) << std::endl;
}
Unfortunately at the moment parsers do not like to have initializer_list
as argument of operators, so it is not possible to get rid of std::vector<int>
in the second solution.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With