Compact way to write if(..) statement with many equalities - c++

Is there a better way to write code like this:
if (var == "first case" or var == "second case" or var == "third case" or ...)
In Python I can write:
if var in ("first case", "second case", "third case", ...)
which also gives me the opportunity to easily pass the list of good options:
good_values = "first case", "second case", "third case"
if var in good_values
This is just an example: the type of var may be different from a string, but I am only interested in alternative (or) comparisons (==). var may be non-const, while the list of options is known at compile time.
Pro bonus:
laziness of or
compile time loop unrolling
easy to extend to other operators than ==

if you want to expand it compile time you can use something like this
template<class T1, class T2>
bool isin(T1&& t1, T2&& t2) {
return t1 == t2;
}
template<class T1, class T2, class... Ts>
bool isin(T1&& t1 , T2&& t2, T2&&... ts) {
return t1 == t2 || isin(t1, ts...);
}
std::string my_var = ...; // somewhere in the code
...
bool b = isin(my_var, "fun", "gun", "hun");
I did not test it actually, and the idea comes from Alexandrescu's 'Variadic templates are funadic' talk. So for the details (and proper implementation) watch that.
Edit:
in c++17 they introduced a nice fold expression syntax
template<typename... Args>
bool all(Args... args) { return (... && args); }
bool b = all(true, true, true, false);
// within all(), the unary left fold expands as
// return ((true && true) && true) && false;
// b is false

The any_of algorithm could work reasonably well here:
#include <algorithm>
#include <initializer_list>
auto tokens = { "abc", "def", "ghi" };
bool b = std::any_of(tokens.begin(), tokens.end(),
[&var](const char * s) { return s == var; });
(You may wish to constrain the scope of tokens to the minimal required context.)
Or you create a wrapper template:
#include <algorithm>
#include <initializer_list>
#include <utility>
template <typename T, typename F>
bool any_of_c(const std::initializer_list<T> & il, F && f)
{
return std::any_of(il.begin(), il.end(), std::forward<F>(f));
}
Usage:
bool b = any_of_c({"abc", "def", "ghi"},
[&var](const char * s) { return s == var; });

Alrighty then, you want Radical Language Modification. Specifically, you want to create your own operator. Ready?
Syntax
I'm going to amend the syntax to use a C and C++-styled list:
if (x in {x0, ...}) ...
Additionally, we'll let our new in operator apply to any container for which begin() and end() are defined:
if (x in my_vector) ...
There is one caveat: it is not a true operator and so it must always be parenthesized as it's own expression:
bool ok = (x in my_array);
my_function( (x in some_sequence) );
The code
The first thing to be aware is that RLM often requires some macro and operator abuse. Fortunately, for a simple membership predicate, the abuse is actually not that bad.
#ifndef DUTHOMHAS_IN_OPERATOR_HPP
#define DUTHOMHAS_IN_OPERATOR_HPP
#include <algorithm>
#include <initializer_list>
#include <iterator>
#include <type_traits>
#include <vector>
//----------------------------------------------------------------------------
// The 'in' operator is magically defined to operate on any container you give it
#define in , in_container() =
//----------------------------------------------------------------------------
// The reverse-argument membership predicate is defined as the lowest-precedence
// operator available. And conveniently, it will not likely collide with anything.
template <typename T, typename Container>
typename std::enable_if <!std::is_same <Container, T> ::value, bool> ::type
operator , ( const T& x, const Container& xs )
{
using std::begin;
using std::end;
return std::find( begin(xs), end(xs), x ) != end(xs);
}
template <typename T, typename Container>
typename std::enable_if <std::is_same <Container, T> ::value, bool> ::type
operator , ( const T& x, const Container& y )
{
return x == y;
}
//----------------------------------------------------------------------------
// This thunk is used to accept any type of container without need for
// special syntax when used.
struct in_container
{
template <typename Container>
const Container& operator = ( const Container& container )
{
return container;
}
template <typename T>
std::vector <T> operator = ( std::initializer_list <T> xs )
{
return std::vector <T> ( xs );
}
};
#endif
Usage
Great! Now we can use it in all the ways you would expect an in operator to be useful. According to your particular interest, see example 3:
#include <iostream>
#include <set>
#include <string>
using namespace std;
void f( const string& s, const vector <string> & ss ) { cout << "nope\n\n"; }
void f( bool b ) { cout << "fooey!\n\n"; }
int main()
{
cout <<
"I understand three primes by digit or by name.\n"
"Type \"q\" to \"quit\".\n\n";
while (true)
{
string s;
cout << "s? ";
getline( cin, s );
// Example 1: arrays
const char* quits[] = { "quit", "q" };
if (s in quits)
break;
// Example 2: vectors
vector <string> digits { "2", "3", "5" };
if (s in digits)
{
cout << "a prime digit\n\n";
continue;
}
// Example 3: literals
if (s in {"two", "three", "five"})
{
cout << "a prime name!\n\n";
continue;
}
// Example 4: sets
set <const char*> favorites{ "7", "seven" };
if (s in favorites)
{
cout << "a favorite prime!\n\n";
continue;
}
// Example 5: sets, part deux
if (s in set <string> { "TWO", "THREE", "FIVE", "SEVEN" })
{
cout << "(ouch! don't shout!)\n\n";
continue;
}
// Example 6: operator weirdness
if (s[0] in string("014") + "689")
{
cout << "not prime\n\n";
continue;
}
// Example 7: argument lists unaffected
f( s, digits );
}
cout << "bye\n";
}
Potential improvements
There are always things that can be done to improve the code for your specific purposes. You can add a ni (not-in) operator (Add a new thunk container type). You can wrap the thunk containers in a namespace (a good idea). You can specialize on things like std::set to use the .count() member function instead of the O(n) search. Etc.
Your other concerns
const vs mutable : not an issue; both are usable with the operator
laziness of or : Technically, or is not lazy, it is short-circuited. The std::find() algorithm also short-circuits in the same way.
compile time loop unrolling : not really applicable here. Your original code did not use loops; while std::find() does, any loop unrolling that may occur is up to the compiler.
easy to extend to operators other than == : That actually is a separate issue; you are no longer looking at a simple membership predicate, but are now considering a functional fold-filter. It is entirely possible to create an algorithm that does that, but the Standard Library provides the any_of() function, which does exactly that. (It's just not as pretty as our RLM 'in' operator. That said, any C++ programmer will understand it easily. Such answers have already been proffered here.)
Hope this helps.

First, I recommend using a for loop, which is both the easiest and
most readable solution:
for (i = 0; i < n; i++) {
if (var == eq[i]) {
// if true
break;
}
}
However, some other methods also available, e.g., std::all_of, std::any_of, std::none_of (in #include <algorithm>).
Let us look at the simple example program which contains all the above keywords
#include <vector>
#include <numeric>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <functional>
int main()
{
std::vector<int> v(10, 2);
std::partial_sum(v.cbegin(), v.cend(), v.begin());
std::cout << "Among the numbers: ";
std::copy(v.cbegin(), v.cend(), std::ostream_iterator<int>(std::cout, " "));
std::cout << '\\n';
if (std::all_of(v.cbegin(), v.cend(), [](int i){ return i % 2 == 0; }))
{
std::cout << "All numbers are even\\n";
}
if (std::none_of(v.cbegin(), v.cend(), std::bind(std::modulus<int>(),
std::placeholders::_1, 2)))
{
std::cout << "None of them are odd\\n";
}
struct DivisibleBy
{
const int d;
DivisibleBy(int n) : d(n) {}
bool operator()(int n) const { return n % d == 0; }
};
if (std::any_of(v.cbegin(), v.cend(), DivisibleBy(7)))
{
std::cout << "At least one number is divisible by 7\\n";
}
}

You may use std::set to test if var belongs to it. (Compile with c++11 enabled)
#include <iostream>
#include <set>
int main()
{
std::string el = "abc";
if (std::set<std::string>({"abc", "def", "ghi"}).count(el))
std::cout << "abc belongs to {\"abc\", \"def\", \"ghi\"}" << std::endl;
return 0;
}
The advantage is that std::set<std::string>::count works in O(log(n)) time (where is n is number of strings to test) comparing to non compact if witch is O(n) in general. The disadvantage is that construction of the set takes O(n*log(n)). So, construct it once, like:
static std::set<std::string> the_set = {"abc", "def", "ghi"};
But, IMO it would be better to leave the condition as is, unless it contains more than 10 strings to check. The performance advantages of using std::set for such a test appears only for big n. Also, simple non compact if is easier to read for average c++ developer.

The closest thing would be something like:
template <class K, class U, class = decltype(std::declval<K>() == std::declval<U>())>
bool in(K&& key, std::initializer_list<U> vals)
{
return std::find(vals.begin(), vals.end(), key) != vals.end();
}
We need to take an argument of type initializer_list<U> so that we can pass in a braced-init-list like {a,b,c}. This copies the elements, but presumably we're going doing this because we're providing literals so probably not a big deal.
We can use that like so:
std::string var = "hi";
bool b = in(var, {"abc", "def", "ghi", "hi"});
std::cout << b << std::endl; // true

If you have access to C++14 (not sure if this works with C++11) you could write something like this:
template <typename T, typename L = std::initializer_list<T>>
constexpr bool is_one_of(const T& value, const L& list)
{
return std::any_of(std::begin(list), std::end(list), [&value](const T& element) { return element == value; });
};
A call would look like this:
std::string test_case = ...;
if (is_one_of<std::string>(test_case, { "first case", "second case", "third case" })) {...}
or like this
std::string test_case = ...;
std::vector<std::string> allowedCases{ "first case", "second case", "third case" };
if (is_one_of<std::string>(test_case, allowedCases)) {...}
If you don't like to "wrap" the allowed cases into a list type you can also write a little helper function like this:
template <typename T, typename...L>
constexpr bool is_one_of(const T& value, const T& first, const L&... next) //First is used to be distinct
{
return is_one_of(value, std::initializer_list<T>{first, next...});
};
This will allow you to call it like this:
std::string test_case = ...;
if (is_one_of<std::string>(test_case, "first case", "second case", "third case" )) {...}
Complete example on Coliru

Worth noting that in most Java and C++ code I've seen, listing 3 or so conditionals out is the accepted practice. It's certainly more readable than "clever" solutions. If this happens so often it's a major drag, that's a design smell anyway and a templated or polymorphic approach would probably help avoid this.
So my answer is the "null" operation. Just keep doing the more verbose thing, it's most accepted.

You could use a switch case. Instead of having a list of separate cases you could have :
include
using namespace std;
int main ()
{
char grade = 'B';
switch(grade)
{
case 'A' :
case 'B' :
case 'C' :
cout << "Well done" << endl;
break;
case 'D' :
cout << "You passed" << endl;
break;
case 'F' :
cout << "Better try again" << endl;
break;
default :
cout << "Invalid grade" << endl;
}
cout << "Your grade is " << grade << endl;
return 0;
}
So you can group your results together: A, B and C will output "well done".
I took this example from Tutorials Point:
http://www.tutorialspoint.com/cplusplus/cpp_switch_statement.htm

Related

How to implement a map with three keys in C++ STL?

So, I have a class
class table()
{
public:
string product, region, province ,price;
};
so i have an array of objects of the above shown class and my objective is to write a function with input as product, region, province the function searches this in the array and returns the price.
Now to search efficiently with least time I thought of using stl map in c++ but i require to have 3 keys in my map with price as the value,so I used this.
struct key
{
string product, region, province;
};
and my map definition is this.
unordered_map<key,string> mp;
Is this even practical to have three keys in map?
does having 3 keys affect the search time complexity for the map?
I am still pretty new to computer science field so please forgive me for any mistake in this question,
and also if i am completely wrong with the map idea a slight push in the right direction for me will be very helpful.
thankyou for your time.
if you are using map then you can use tuple<type1, type2....>
map<tuple<int, int , int> , string> foo;
foo.insert(make_tuple(1,2,3), "bar");
foo[make_tuple(1,3,1)] = "bar1";
foo[{2,2,3}] = "bar2";
c++ tuple
Yes you can do this with std::unordered_map, and it isn't as difficult as it may first seem. All a std::unordered_map cares about is:
The key type must be hashable using either a default hash algorithm or one provided to the container as a template-parameter type or a construction instance.
The key type must support equivalence checks (i.e. comparing two key instances for equivalence using either a custom "equals" type similar to the hasher template parameter argument, or the default std::equals, which uses operator == with two instances).
This is easier to see than to explain. Below is a trivial example:
#include <iostream>
#include <algorithm>
#include <string>
#include <cstdlib>
#include <tuple>
#include <unordered_map>
struct MyKey
{
struct Hash
{
// jacked up derivation of bernstiens string hasher
std::size_t operator()(MyKey const& key) const
{
std::size_t hash = 5381u;
for (auto c : key.s1)
hash = (hash << 5) + hash + c;
for (auto c : key.s2)
hash = (hash << 5) + hash + c;
for (auto c : key.s3)
hash = (hash << 5) + hash + c;
return hash;
}
};
std::string s1, s2, s3;
// equivalence determination.
bool operator ==(MyKey const& key) const
{
return std::tie(s1, s2, s3) == std::tie(key.s1, key.s2, key.s3);
}
};
int main()
{
std::unordered_map<MyKey, int, MyKey::Hash> ht;
ht.insert(std::make_pair<MyKey>({ "one", "two", "three" }, 42));
ht.insert(std::make_pair<MyKey>({ "four", "five", "six" }, 1999));
ht.insert(std::make_pair<MyKey>({ "seven", "eight", "nine" }, 1999));
auto it = ht.find(MyKey{ "one", "two", "three" });
if (it != ht.end())
std::cout << it->second << '\n';
it = ht.find(MyKey{ "four", "five", "six" });
if (it != ht.end())
std::cout << it->second << '\n';
it = ht.find(MyKey{ "seven", "eight", "nine" });
if (it != ht.end())
std::cout << it->second << '\n';
// shoudl NOT find anything
it = ht.find(MyKey{ "one", "three", "two" });
if (it != ht.end())
std::cout << it->second << '\n';
}
To answer probably the most important part of your question, no this does NOT affect search time. Obviously it takes longer to generate a hash value from three string than from one, but once that value is acquired the search mechanics are identical to any other unordered_map. If a collision is found, the equivalence check kicks in, and again, that's unavoidable, but not going affect the big-O complexity of your overall performance profile.
std::map is a touch easier to get working
struct key {
std::string product, region, province;
auto as_tie() const{
return std::tie(product, region, province);
}
friend bool operator<( key const& lhs, key const& rhs ){
return lhs.as_tie()<rhs.as_tie();
}
};
now key works as a key in a std::map. Here I let std tuple (via std tie) implement my < operator.
For an unordered map, you need to specialize std hash and provide == (or pass a hasher/equality function object to the template).
In C++20 you can just
auto operator<=>(key const&)const =default;
instead of the tie stuff and get map to work.
3 part keys don't change the big-O complexity of maps, ordered or not.
Unordered map still needs a custom hash.
Firstly, you'll want to be able to hash multiple key fields to provide one high quality hash value, and - in the style of boost hash_combine - you can do that with:
template <class T>
inline void hash_combine(std::size_t& seed, T const& v) {
seed ^= std::hash<T>()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
...combined with a general-purpose tuple hash function...
struct hash_tuple {
auto operator()(const auto& tuple) const {
std::size_t seed = 0;
std::apply([&](const auto& ...element){(..., hash_combine(seed, element));}, tuple);
return seed;
}
};
The above will work for any length of tuple, and any contained types that are themselves hashable.
You can then either use an unordered_map from a std::tuple of your key fields to the price double, as in:
using key = std::tuple<std::string, std::string, std::string>;
std::unordered_map<key, double, hash_tuple> m;
// ...then just use the map...
m[{"abc", "def", "ghi"}] = 3.14;
...or, you might want to have a struct with your keys and price combined...
struct X {
std::string a, b, c;
double price_;
auto tie_keys() const { return std::tie(a, b, c); }
bool operator==(const X& rhs) const {
return tie_keys() == rhs.tie_keys();
}
friend std::ostream& operator<<(std::ostream& os, const X& x) {
return os << x.a << ' ' << x.b << ' ' << x.c << ' ' << x.price_;
}
};
...and store those in an unordered_set<>...
auto hash_fn = [](const X& x) { return hash_tuple{}(x.tie_keys()); };
std::unordered_set<X, decltype(hash_fn)> m2;
// ...and use it...
m2.emplace("ab", "cde", "fg", 3.14);
m2.emplace("hij", "kl", "mn", 2.71);
for (const auto& x : m2)
std::cout << x << '\n';
You'll need various headers of course...
#include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <string>
#include <tuple>
does having 3 keys affect the search time complexity for the map?
Not if you have a decent hash function.

Using boost mp11 to switch on runtime value efficiently(breaking when processing function is done)

I have the following code where I implement dispatching on runtime value to interpret the data in certain way(in this toy example data can be either uint8_t or short).
Code seems to work, but I am wondering if I can somehow microoptimize the code so that when I have a hit(processing function matches) processing is stopped (currently even if first element of tuple is a "handler" entire tuple is iterated over at runtime).
#include <boost/mp11/tuple.hpp>
#include <iostream>
uint8_t data[4] = {0,1,100,2};
template<int runtimeId, typename T>
struct kindToType{
static constexpr int id = runtimeId;
using type = T;
};
const auto print =[]<typename T> (const T* data){
if constexpr(std::is_same_v<short, std::remove_cvref_t<T>>){
const short* values = (const short*)data;
std::cout << values[0] << " " << values[1] << std::endl;
} else if constexpr(std::is_same_v<uint8_t, std::remove_cvref_t<T>>){
const uint8_t* values = (const uint8_t*)data;
std::cout << (int)values[0] << " " << (int)values[1]<< " " << (int)values[2] << " " << (int)values[3] << std::endl;;
}
};
static constexpr std::tuple<kindToType<10, uint8_t>, kindToType<11, short>> mappings{};
void dispatch(int kind){
boost::mp11::tuple_for_each(mappings, [kind]<typename Mapping>(const Mapping&) {
if (Mapping::id == kind)
{
print((typename Mapping::type*)data);
}
});
}
int main()
{
// no guarantee that kind is index like(e.g. for two values
// it can have values 47 and 1701)
dispatch(10);
dispatch(11);
}
Notes:
I can not/want to use std::variant.
I do not want to use std::map or std::unordered map(where value is std::function)
I know this is premature optimization(even 10 integer comparisons is cheap assuming handlers do nontrivial amount of work).
my handlers are unique, i.e. it is std::map like thing, not std::multimap like thing so it is fine to break;.
kind of id used for runtime values is not guaranteed to have values in [0, n-1].
I am fine with C++20 solution as long as it is implemented in at least 1 compiler.
The runtime performance of this heavily depends on the size of your tuple. You can make your own for_each_tuple implementation that does an early out when your function gets executed:
template<typename FuncTuple, typename Selector>
void tuple_for_each(FuncTuple const& funcTuple, Selector selector)
{
std::apply([selector](auto const& ...funcs)
{
(void)(selector(funcs) || ...);
}, funcTuple);
}
your dispatch would then look like this:
void dispatch(int kind)
{
tuple_for_each(mappings, [kind]<typename Mapping>(const Mapping&)
{
std::cout << "loop, ";
if (Mapping::id == kind)
{
print((typename Mapping::type*)data);
return true;
}
return false;
});
}
If you get rid of the template in your lambda and use auto instead this code will compile with C++17. We use operator short circuiting to our advantage so the compiler will provide an early out for us. Here is the full code.
Also, note that the cast (const short*)data is UB.

How to use std::any_of for a beginner?

I want to compare one value against several others and check if it matches at least one of those values, I assumed it would be something like
if (x = any_of(1, 2 ,3)
// do something
But the examples of it I've seen online have been
bool any_of(InputIt first, InputIt last, UnaryPredicate)
What does that mean?
New to c++ so apologies if this is a stupid question.
There is plenty of literature and video tutorials on the subject of "iterators in C++", you should do some research in that direction because it's a fundamental concept in C++.
A quick summary on the matter: an iterator is something that points to an element in a collection (or range) of values. A few examples of such collections:
std::vector is the most common one. It's basically a resizable array.
std::list is a linked list.
std::array is a fixed size array with some nice helpers around C style arrays
int myInt[12] is a C style array of integers. This one shouldn't be used anymore.
Algorithms from the C++ standard library that operate on a collection of values (such as std::any_of) take the collection by two iterators. The first iterator InputIt first points to the beginning of said collection, while InputIt last points to the end of the collection (actually one past the end).
A UnaryPredicate is a function that takes 1 argument (unary) and returns a bool (predicate).
In order to make std::any_of do what you want, you have to put your values in a collection and x in the UnaryPredicate:
int x = 3;
std::vector values = {1, 2, 3};
if (std::any_of(values.begin(), values.end(), [x](int y) { return x == y; }))
// ...
The UnaryPredicate in this case is a lambda function.
As you can see this is quite verbose code given your example. But once you have a dynamic amound of values that you want to compare, or you want to check for more complex things than just equality, this algorithm becomes way more beneficial.
Fun little experiment
Just for fun, I made a little code snippet that implements an any_of like you wanted to have it. It's quite a lot of code and pretty complicated aswell (definitely not beginner level!) but it is very flexible and actually nice to use. The full code can be found here.
Here is how you would use it:
int main()
{
int x = 7;
std::vector dynamic_int_range = {1, 2, 3, 4, 5, 6, 7, 8};
if (x == any_of(1, 2, 3, 4, 5))
{
std::cout << "x is in the compile time collection!\n";
}
else if (x == any_of(dynamic_int_range))
{
std::cout << "x is in the run time collection!\n";
}
else
{
std::cout << "x is not in the collection :(\n";
}
std::string s = "abc";
std::vector<std::string> dynamic_string_range = {"xyz", "uvw", "rst", "opq"};
if (s == any_of("abc", "def", "ghi"))
{
std::cout << "s is in the compile time collection!\n";
}
else if (s == any_of(dynamic_string_range))
{
std::cout << "s is in the run time collection!\n";
}
else
{
std::cout << "s is not in the collection :(\n";
}
}
And here how it's implemented:
namespace detail
{
template <typename ...Args>
struct ct_any_of_helper
{
std::tuple<Args...> values;
constexpr ct_any_of_helper(Args... values) : values(std::move(values)...) { }
template <typename T>
[[nodiscard]] friend constexpr bool operator==(T lhs, ct_any_of_helper const& rhs) noexcept
{
return std::apply([&](auto... vals) { return ((lhs == vals) || ...); }, rhs.values);
}
};
template <typename Container>
struct rt_any_of_helper
{
Container const& values;
constexpr rt_any_of_helper(Container const& values) : values(values) { }
template <typename T>
[[nodiscard]] friend constexpr bool operator==(T&& lhs, rt_any_of_helper&& rhs) noexcept
{
return std::any_of(cbegin(rhs.values), cend(rhs.values), [&](auto val)
{
return lhs == val;
});
}
};
template <typename T>
auto is_container(int) -> decltype(cbegin(std::declval<T>()) == cend(std::declval<T>()), std::true_type{});
template <typename T>
std::false_type is_container(...);
template <typename T>
constexpr bool is_container_v = decltype(is_container<T>(0))::value;
}
template <typename ...Args>
[[nodiscard]] constexpr auto any_of(Args&&... values)
{
using namespace detail;
if constexpr (sizeof...(Args) == 1 && is_container_v<std::tuple_element_t<0, std::tuple<Args...>>>)
return rt_any_of_helper(std::forward<Args>(values)...);
else
return ct_any_of_helper(std::forward<Args>(values)...);
}
In case an expert sees this code and wants to complain about the dangling reference: come on, who would write someting like this:
auto a = any_of(std::array {1, 2, 3, 4});
if (x == std::move(a)) // ...
That's not what this function is for.
Your values must already exist somewhere else, it is very likely that it will be a vector.
std::any_of operates on iterators.
Iterators in C++ are ranges, two values that tell you where is the beginning, and where is the end of the range.
Most C++ Standard Template Library collections, including std::vector, support iterator API, and so you can use std::any_of on them.
For the sake of a full example, lets check if a vector contains 42 in over the top way, just to use std::any_of.
Since we only want to check if value in vector exists without changing anything (std::any_of doesn't modify the collection), we use .cbegin() and .cend() that return constant beginning and end of the vector, those are important to std::any_of, as it has to iterate over the entire vector to check if there's at least one value matching the given predicate.
The last parameter must be unary predicate, that means that it is a function, that accepts a single argument, and returns whether given argument fits some criteria.
To put it simply, std::any_of is used to check whether there's at least one value in a collection, that has some property that you care about.
Code:
#include <algorithm>
#include <iostream>
#include <vector>
bool is_42(int value) {
return value == 42;
}
int main() {
std::vector<int> vec{
1, 2, 3,
// 42 // uncomment this
};
if(std::any_of(vec.cbegin(), vec.cend(), is_42)) {
std::cout << "42 is in vec" << std::endl;
} else {
std::cout << "42 isn't in vec" << std::endl;
}
}
As stated by user #a.abuzaid, you can create your own method for this. The method they provided, however, lacks in a number of areas stated in the comments of the answer. I can't really get my head around std::any_of as of right now and just decided to create this template:
template <typename Iterable, typename type>
bool any_of(Iterable iterable, type value) {
for (type comparison : iterable) {
if (comparison == value) {
return true;
}
}
return false;
}
An example use here would be if (any_of(myVectorOfStrings, std::string("Find me!"))) { do stuff }, in which the iterable is a vector of strings and the value is the string "Find me!".
You can just create a function where you are comparing x to two other numbers to check if they are the same for instance
bool anyof(int x, int y, int z) {
if ((x == y) || (x == z))
return true;
}
and then within your main you can call the function like this:
if (anyof(x, 1, 2))
cout << "Matches a number";

`c++17` ranged for loop over std::vectors with value and index [duplicate]

Is there an equivalent to the range-based enumerate loop from python in C++?
I would imagine something like this.
enumerateLoop (auto counter, auto el, container) {
charges.at(counter) = el[0];
aa.at(counter) = el[1];
}
Can this be done with templates or macros?
I'm aware that I can just use an old school for-loop and iterate until I reach container.size(). But I'm interested how this would be solved using templates or macros.
EDIT
I played a bit with boost iterators after the hint in the comments. I got another working solution using C++14.
template <typename... T>
auto zip(const T &... containers) -> boost::iterator_range<boost::zip_iterator<
decltype(boost::make_tuple(std::begin(containers)...))>> {
auto zip_begin =
boost::make_zip_iterator(boost::make_tuple(std::begin(containers)...));
auto zip_end =
boost::make_zip_iterator(boost::make_tuple(std::end(containers)...));
return boost::make_iterator_range(zip_begin, zip_end);
}
template <typename T>
auto enumerate(const T &container) {
return zip(boost::counting_range(0, static_cast<int>(container.size())),
container);
}
https://gist.github.com/kain88-de/fef962dc1c15437457a8
Enumeration of multiple variables has been an idiom since C. The only complication is that you can't declare both variables in the initializer of the for loop.
int index;
for (auto p = container.begin(), index = 0; p != container.end(); ++p, ++index)
I don't think it gets any simpler (or more powerful) than that.
There is a pre C++11 solution in boost to this: boost.range.indexed.
Unfortunately it doesn't work with C++11 range based for-loops, only old style verbose loops. However with C++17 it should be become (almost) as easy as in python using structured bindings
Then it should be possible implement something that works like this:
for (auto& [n,x] : enumerate(vec)) x = n;
So, a bit of waiting still ;)
I wrote something for this a while back.
Essentially, you need to wrap an iterator and give it pair semantics.
AFAIK, there's nothing like this built into the language. And I don't think boost has it either. You pretty much have to roll your own.
// Wraps a forward-iterator to produce {value, index} pairs, similar to
// python's enumerate()
template <typename Iterator>
struct EnumerateIterator {
private:
Iterator current;
Iterator last;
size_t index;
bool atEnd;
public:
typedef decltype(*std::declval<Iterator>()) IteratorValue;
typedef pair<IteratorValue const&, size_t> value_type;
EnumerateIterator()
: index(0), atEnd(true) {}
EnumerateIterator(Iterator begin, Iterator end)
: current(begin), last(end), index(0) {
atEnd = current == last;
}
EnumerateIterator begin() const {
return *this;
}
EnumerateIterator end() const {
return EnumerateIterator();
}
EnumerateIterator operator++() {
if (!atEnd) {
++current;
++index;
atEnd = current == last;
}
return *this;
}
value_type operator*() const {
return {*current, index};
}
bool operator==(EnumerateIterator const& rhs) const {
return
(atEnd && rhs.atEnd) ||
(!atEnd && !rhs.atEnd && current == rhs.current && last == rhs.last);
}
bool operator!=(EnumerateIterator const& rhs) const {
return !(*this == rhs);
}
explicit operator bool() const {
return !atEnd;
}
};
template<typename Iterable>
EnumerateIterator<decltype(std::declval<Iterable>().begin())> enumerateIterator(Iterable& list) {
return EnumerateIterator<decltype(std::declval<Iterable>().begin())>(list.begin(), list.end());
}
template<typename ResultContainer, typename Iterable>
ResultContainer enumerateConstruct(Iterable&& list) {
ResultContainer res;
for (auto el : enumerateIterator(list))
res.push_back(move(el));
return res;
}
C++17 and structured bindings makes this look OK - certainly better than some ugly mutable lambda with a local [i = 0](Element&) mutable or whatever I've done before admitting that probably not everything should be shoehorned into for_each() et al. - and than other solutions that require a counter with scope outside the for loop.
for (auto [it, end, i] = std::tuple{container.cbegin(), container.cend(), 0};
it != end; ++it, ++i)
{
// something that needs both `it` and `i`ndex
}
You could make this generic, if you use this pattern often enough:
template <typename Container>
auto
its_and_idx(Container&& container)
{
using std::begin, std::end;
return std::tuple{begin(container), end(container), 0};
}
// ...
for (auto [it, end, i] = its_and_idx(foo); it != end; ++it, ++i)
{
// something
}
C++ Standard proposal P2164 proposes to add views::enumerate, which would provide a view of a range giving both reference-to-element and index-of-element to a user iterating it.
We propose a view enumerate whose value type is a struct with 2 members index and value representing respectively the position and value of the elements in the adapted range.
[ . . .]
This feature exists in some form in Python, Rust, Go (backed into the language), and in many C++ libraries: ranges-v3, folly, boost::ranges (indexed).
The existence of this feature or lack thereof is the subject of recurring stackoverflow questions.
Hey, look! We're famous.
You can also more elegantly use the auto ranges available since C++11:
int i = 0;
for (auto& el : container){
charges.at(counter) = el[0];
aa.at(counter) = el[1];
++i;
}
You still have to count the i up by hand, though.
Here's a macro-based solution that probably beats most others on simplicity, compile time, and code generation quality:
#include <iostream>
#define fori(i, ...) if(size_t i = -1) for(__VA_ARGS__) if(i++, true)
int main() {
fori(i, auto const & x : {"hello", "world", "!"}) {
std::cout << i << " " << x << std::endl;
}
}
Result:
$ g++ -o enumerate enumerate.cpp -std=c++11 && ./enumerate
0 hello
1 world
2 !
Tobias Widlund wrote a nice MIT licensed Python style header only enumerate (C++17 though):
GitHub
Blog Post
Really nice to use:
std::vector<int> my_vector {1,3,3,7};
for(auto [i, my_element] : en::enumerate(my_vector))
{
// do stuff
}
Boost::Range supports this as of 1.56.
#include <boost/range/adaptor/indexed.hpp>
#include <boost/assign.hpp>
#include <iterator>
#include <iostream>
#include <vector>
int main(int argc, const char* argv[])
{
using namespace boost::assign;
using namespace boost::adaptors;
std::vector<int> input;
input += 10,20,30,40,50,60,70,80,90;
// for (const auto& element : index(input, 0)) // function version
for (const auto& element : input | indexed(0))
{
std::cout << "Element = " << element.value()
<< " Index = " << element.index()
<< std::endl;
}
return 0;
}

C++ storing a value in an unordered pair

I want to store a floating point value for an unordered pair of an integers. I am unable to find any kind of easy to understand tutorials for this. E.g for the unordered pair {i,j} I want to store a floating point value f. How do I insert, store and retrieve values like this?
Simple way to handle unordered int pairs is using std::minmax(i,j) to generate std::pair<int,int>. This way you can implement your storage like this:
std::map<std::pair<int,int>,float> storage;
storage[std::minmax(i,j)] = 0.f;
storage[std::minmax(j,i)] = 1.f; //rewrites storage[(i,j)]
Admittedly proper hashing would give you some extra performance, but there is little harm in postponing this kind of optimization.
Here's some indicative code:
#include <iostream>
#include <unordered_map>
#include <utility>
struct Hasher
{
int operator()(const std::pair<int, int>& p) const
{
return p.first ^ (p.second << 7) ^ (p.second >> 3);
}
};
int main()
{
std::unordered_map<std::pair<int,int>, float, Hasher> m =
{ { {1,3}, 2.3 },
{ {2,3}, 4.234 },
{ {3,5}, -2 },
};
// do a lookup
std::cout << m[std::make_pair(2,3)] << '\n';
// add more data
m[std::make_pair(65,73)] = 1.23;
// output everything (unordered)
for (auto& x : m)
std::cout << x.first.first << ',' << x.first.second
<< ' ' << x.second << '\n';
}
Note that it relies on the convention that you store the unordered pairs with the lower number first (if they're not equal). You might find it convenient to write a support function that takes a pair and returns it in that order, so you can use that function when inserting new values in the map and when using a pair as a key for trying to find a value in the map.
Output:
4.234
3,5 -2
1,3 2.3
65,73 1.23
2,3 4.234
See it on ideone.com. If you want to make a better hash function, just hunt down an implementation of hash_combine (or use boost's) - plenty of questions here on SO explaining how to do that for std::pair<>s.
You implement a type UPair with your requirements and overload ::std::hash (which is the rare occasion that you are allowed to implement something in std).
#include <utility>
#include <unordered_map>
template <typename T>
class UPair {
private:
::std::pair<T,T> p;
public:
UPair(T a, T b) : p(::std::min(a,b),::std::max(a,b)) {
}
UPair(::std::pair<T,T> pair) : p(::std::min(pair.first,pair.second),::std::max(pair.first,pair.second)) {
}
friend bool operator==(UPair const& a, UPair const& b) {
return a.p == b.p;
}
operator ::std::pair<T,T>() const {
return p;
}
};
namespace std {
template <typename T>
struct hash<UPair<T>> {
::std::size_t operator()(UPair<T> const& up) const {
return ::std::hash<::std::size_t>()(
::std::hash<T>()(::std::pair<T,T>(up).first)
) ^
::std::hash<T>()(::std::pair<T,T>(up).second);
// the double hash is there to avoid the likely scenario of having the same value in .first and .second, resulinting in always 0
// that would be a problem for the unordered_map's performance
}
};
}
int main() {
::std::unordered_map<UPair<int>,float> um;
um[UPair<int>(3,7)] = 3.14;
um[UPair<int>(8,7)] = 2.71;
return 10*um[::std::make_pair(7,3)]; // correctly returns 31
}