C++ scope of variables inside try - c++

Consider this code:
try {
const Asdf &a = map1.at(index1);
const Bsdf &b = map2.at(index2);
} catch(std::out_of_range&) {
return false;
}
// <code>
std::cout<<a[b[42]]; // May throw std::out_of_range which should not be caught here.
return true;
<code> uses a and b. I have two options:
Put <code> in the try block
Take pointers in the try block, dereference them afterwards
The first option is wrong because if <code> throws std::out_of_range the function will return false, which should only happen if the map lookup fails.
The second option can be a bit ugly:
const Asdf *a;
const Bsdf *b;
try {
a = &map1.at(index1); // What?
b = &map2.at(index2);
} catch(std::out_of_range&) {
return false;
}
std::cout << (*a)[(*b)[42]];
return true;
Is there a better way? Something like try-except-else in Python would be nice, but that doesn't exist in C++.

It's not necessary to do any exception handling. std::map::find, given a key, will give you an iterator. If the element doesn't exist within the map, then find will return the end iterator (i.e. map.end()).
When de-referencing the iterator, you will receive a pair of values. The first being the key and the second being the object.
auto aIt = map1.find(index1);
auto bIt = map2.find(index2);
if(aIt == map1.end() || bIt == map2.end())
{
return false;
}
const Asdf &a = aIt->second;
const Bsdf &b = bIt->second;
std::cout << a[b[42]];
return true;
Note that iterators in C++ are defined such that the begin iterator is at the start and the end iterator is past the last element (http://en.cppreference.com/w/cpp/iterator/end), i.e. the range for iterators within a container is: [begin, end).

Solution 1:
Why include the code in the try catch, embedding it in its own try catch block to make the difference between the two cases?
try {
const Asdf &a = map1.at(index1);
const Bsdf &b = map2.at(index2);
try {
// <code>
std::cout<<a[b[42]]; // May throw std::out_of_range which should not be caught here.
} catch (std::out_of_range&) {}
} catch(std::out_of_range&) {
return false;
}
return true;
But of course in this approach you can't forward to the outside of your function an out_of_range that would occur in your <code>.
Solution 2:
The other alternative is to simply check existence of the keys using map::count() without the need for exception catching:
if (map1.count(index1)==0 || map2.count(index2)==0) {
return false;
}
const Asdf &a = map1.at(index1);
const Bsdf &b = map2.at(index2);
// <code>
std::cout<<a[b[42]];
return true;

I like Miguel's solution the best, becuase it doesn't involve exception handling (when it is not called for).
But aside from that, here's another option (which I like for being short and keeping the low map operations count):
bool retval = false;
try{
const Asdf &a=map1.at(index1);
const Bsdf &b=map2.at(index2);
retval = true;
std::cout<<a[b[42]];
}catch(std::out_of_range&){
return reval;
}
// more code?
return reval;

An unconventional solution is to exploit the capturing of lambdas to extend the scope of the reference variables beyond the scope of the block. Since the objects referred by the references is valid beyond the scope block, the captured references aren't stale when used later as long as the map object remains in scope.
As an example
#include <functional>
#include <vector>
int main()
{
std::vector<std::vector< int > > map1 = { { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 } };
std::function<int()> fn;
try{
const auto &a = map1.at(1);
const auto &b = map1.at(2);
fn = [&]() {return a[b[1]]; };
}
catch (std::out_of_range&){
return false;
}
fn(); // Any exception thrown here would be caught separately from the above try catch block
}

One work around is to ensure that map actually does contain the item. It adds to overhead, but is less worse of the many worse ways I know.
try{
map1.at(index1);
map2.at(index2);
}catch(std::out_of_range&){
return false;
}
const Asdf &a=map1.at(index1);
const Bsdf &b=map2.at(index2);
Or if written in a little better way (Sorry no performance gain, only readability) unless you want to sacrifice the constness of references.
if(map1.find(index1) == map1.end() || map2.find(index2) == map2.end()) return false;
const Asdf &a=map1.at(index1);
const Bsdf &b=map2.at(index2);
You can also use std::map::const_iterator without the need of try-catch block.
std::map::const_iterator a = map1.find(index1);
if(a == map1.end()) return false;
std::map::const_iterator b = map1.find(index2);
if(b == map2.end()) return false;
Do whatever with read-only a->second and b->second.

Related

c++ More efficient data structure and algorithm for making a Counter. i used look up tables

My problem is : i gave a series of queries, and a series of references, and i want to count the number of occurance of said keys between them, but only if they have matching keys. I choose to have an LUT because i think it will help me efficiently, but im not sure if there are better ways, or the way im using LUT is not efficient enough.
i have the following data structures.
unordered_map <int, set<int>> Reference_map1, Reference_map2, ... , Reference_mapM;
// to story all the reference maps by their neightas
unordered_map <string, unordered_map <int, set<int>>> ReferenceMaps;
unordered_map <int, set<string>> LUT // look up table
// N is significantly greater than M
unordered_map <int, set<int>> query_map1, query_map2, ... , query_mapN;
Example of Reference_mapi and query_mapj
Reference_map1[111] = {0, 1, 2};
Reference_map1[333] = {1, 2, 3};
Reference_map1[888] = {2, 8, 0};
Reference_map2[111] = {1, 5, 9};
Reference_map2[999] = {0, 7, 4};
ReferenceMaps['Reference_map1']=Reference_map1;
ReferenceMaps['Reference_map2']=Reference_map2;
query_map1[111] = {8, 2, 6};
query_map1[333] = {4, 7, 3};
query_map2[222] = {3, 6, 8};
query_map2[999] = {2, 3, 5};
How i store my look up table LUT
This is so that for whatever keys i get from 'query_mapj', i only get the necessary Reference_mapis
LUT[111] = {'Reference_map1', 'Reference_map2'}
LUT[333] = {'Reference_map1'}
LUT[888] = {'Reference_map1'}
LUT[999] = {'Reference_map2'}
For example 111 from query_map1 gives both 'Reference_map1', 'Reference_map2' as they have the key 111.
On the other hand, 999 from query_map2 only gives 'Reference_map2' as only it have the key 999.
So it will go like this:
unordered_map<string, int> MakeCounter(
unordered_map <int, set<int>> &query_map,
unordered_map <string, unordered_map <int, set<int>>> &ReferenceMaps
){
unordered_map<string, int> RefName_Counter;
set<string> ReferenceNameSet;
// Update the RefName_Counter
for (const auto &key2nameset:query_map) {
// Check if this hash is in the LUT
if (LUT.count(key2nameset.first) <= 0){ continue; }
// Update Counter
ReferenceNameSet = LUT[key2nameset.first];
for (const auto &it : ReferenceNameSet){
if (RefName_Counter.count(it) > 0)
RefName_Counter[it]++;
else
RefName_Counter[it] = 1;
}
}
return RefName_Counter;
}
// The results should be like this
Counter1 = MakeCounter(query_map1, ReferenceMaps);
/*
Counter1['Reference_map1'] = 2; // because they share keys : 111 and 333
Counter1['Reference_map2'] = 1; // because they share keys : 111
*/
Counter2 = MakeCounter(query_map2, ReferenceMaps);
/*
Counter1['Reference_map2'] = 1; // because they share keys : 999
*/
Is there a better way to get Counteri for each respective query_mapi ?
Considering my comment above, here is what I got.
Adjusted to keep original data, but this feels like an extra credit :)
unordered_map<int,int> MakeCounter(const unordered_map <int, set<int>>& qs,
const vector<unordered_map <int, set<int>>>& refs)
{
unordered_map<int, int> counters;
for (size_t i = 0; i < refs.size(); ++i)
{
for (auto q : qs)
{
if (refs[i].find(q.first) != refs[i].end())
counters[i]++;
}
}
return counters;
}
int main()
{
vector<unordered_map <int, set<int>>> References = {
{ {111, { 0, 1, 2 } },
{333, { 1, 2, 3 } },
{888, { 2, 8, 0 } },
},
{ {111, { 1, 5, 9 } },
{999, { 0, 7, 4 } },
}
};
vector<unordered_map <int, set<int>>> Queries = {
{ {111, { 8, 2, 6 } },
{333, { 4, 7, 3 } },
},
{ {222, { 3, 6, 8 } },
{999, { 2, 3, 5 } },
}
};
unordered_map<int, int> m0 = MakeCounter(Queries[0], References);
unordered_map<int, int> m1 = MakeCounter(Queries[1], References);
}
This is rather a comment; I am using "answer" to properly format code fragments.
This searches your LUT twice:
// Check if this hash is in the LUT
if (LUT.count(key2nameset.first) <= 0){ continue; }
// Update Counter
ReferenceNameSet = LUT[key2nameset.first];
It also makes a copy of the set for no reason.
I believe that indexing a non-existing element in the map inserts that element, so
if (RefName_Counter.count(it) > 0)
RefName_Counter[it]++;
else
RefName_Counter[it] = 1;
is effectively:
RefName_Counter[it]++;
So your outer for loop becomes:
for (const auto &key2nameset:query_map) {
// Check if this hash is in the LUT
auto iter = LUT.find(key2nameset.first);
if(iter == LUT.end()) { continue; }
// Update Counter
for (const auto &it : *iter){
RefName_Counter[it]++;
}

How do you recursively merge queues in C++? Assume they are already sorted

I made a function that merges two sorted queues.
Queue<int> merge(Queue<int> a, Queue<int> b){
Queue<int> result;
while (!a.isEmpty() && !b.isEmpty()) {
int a1 = a.peek();
int b1 = b.peek();
if (a1 < b1) {
if (! result.isEmpty()) {
if (result.back() > a1) {
error("queue a is not sorted");
}
}
result.add(a1); // add the element to the result and make sure to remove it from the
a.dequeue(); // input queue so we don't get stuck in an infinite loop
} else {
if (! result.isEmpty()) {
if (result.back() > b1) {
error("queue b is not sorted");
}
}
result.add(b1);
b.dequeue();
}
} while (!a.isEmpty()) {
if (! result.isEmpty()) {
if (result.back() > a.peek()) {
error("queue a is not sorted");
}
}
result.add(a.front());
a.dequeue();
} while (!b.isEmpty()) {
if (! result.isEmpty()) {
if (result.back() > b.peek()) {
error("queue b is not sorted");
}
}
result.add(b.front());
b.dequeue();
}
return result;}
Now, I am trying to merge multiple queues together, recursively. Here is my thought process so far:
Divide the input collection of k sequences into two halves, left and right.
Make a recursive call to recMultiMerge on the "left" half of the sequences to generate one combined, sorted sequence. Then, do the same for the "right" half of the sequences, generating a second combined, sorted sequence.
Using the binary merge function I made above, join the two combined sequences into the final result sequence, which is then returned.
I'm having trouble on the actual recursive call, because I can't figure out how to store the result and recurse again. Here is my attempt so far:
Queue<int> recMultiMerge(Vector<Queue<int>>& all)
{
Queue<int> result = {};
Vector<Queue<int>> left = all.subList(0, all.size() / 2);
Vector<Queue<int>> right = all.subList(all.size() / 2, all.size() / 2);
if (all.isEmpty()) {
return {};
}
else if (left.size() == 1) {
return left[0];
}
else if (right.size() == 1) {
return right[0];
}
else {
Queue<int> leftCombined = recMultiMerge(left);
Queue<int> rightCombined = recMultiMerge(right);
result = merge(leftCombined, rightCombined);
}
return result;
}
The problem is, I can't get it to return more than just the first queue. Here is the problem illustrated in a test case:
on
Vector<Queue<int>> all = {{3, 6, 9, 9, 100}, {1, 5, 9, 9, 12}, {5}, {}, {-5, -5}, {3402}}
it yields
{3, 6, 9, 9, 100}
instead of
{-5, -5, 1, 3, 5, 5, 6, 9, 9, 9, 9, 12, 100, 3402}
Any advice?
An explanation of why your code gives the results you see.
The first call to recMultiMerge has 6 queues. left will be the first three ({3, 6, 9, 9, 100}, {1, 5, 9, 9, 12}, {5}), and right will be the last three ({}, {-5, -5}, {3402}).
Then you make a recursive call with left. In that call, all.size() will be 3. left will have one queue ({3, 6, 9, 9, 100}), and right will also only have one queue ({1, 5, 9, 9, 12}). (I'm assuming the 2nd parameter to Vector.subList is a count.) This will stop at the second if because left.size() == 1. The result will be that first queue.
Now we're back at the first recursive call (having lost the 2nd and 3rd queues), and we again main a recursive call with right (which has 3 queues in it). This will proceed like the last call did, returning the first queue (which in this case is empty) and losing the other two.
Then you merge those two queues ({3, 6, 9, 9, 100} and {}), resulting in your answer: {3, 6, 9, 9, 100}.
This reveals two problems: Not properly dividing a Vector with an odd number of queues in it, and terminating the recursion too early (when the left half of the split only has one queue in it, even though the right half may not be empty).
I'd start with a binary fold.
template<class X, class Op>
X binary_fold( span<X> elems, Op op );
or std::vector<X>, but I prefer span for this.
It splits elems into two pieces, then either recurses or calls op on it.
You can then test binary_fold with debugging code that simply prints the pieces on the left/right in some way, and you can see how the recursion plays out.
Once you have that, you plug back in your merge program and it should just work.
Live example.
Full code:
template<class X>
struct span {
X* b = 0;
X* e = 0;
X* begin() const { return b; }
X* end() const { return e; }
std::size_t size() const { return end()-begin(); }
X& front() const { return *begin(); }
X& back() const { return *(end()-1); }
X* data() const { return begin(); }
bool empty() const { return size()==0; }
span( X* s, X* f ):b(s),e(f) {}
span() = default;
span( X* s, std::size_t l ):span(s, s+l) {}
span( std::vector<X>& v ):span( v.data(), v.size() ) {}
template<std::size_t N>
span( X(&arr)[N] ):span(arr, N) {}
template<std::size_t N>
span( std::array<X, N>& arr ):span(arr.data(), N) {}
span except_front( std::size_t n = 1 ) const {
n = (std::min)(n, size());
return {begin()+n, end()};
}
span only_front( std::size_t n = 1 ) const {
n = (std::min)(n, size());
return {begin(), begin()+n};
}
span except_back( std::size_t n = 1 ) const {
n = (std::min)(n, size());
return {begin(), end()-n};
}
span only_back( std::size_t n = 1 ) const {
n = (std::min)(n, size());
return {end()-n, end()};
}
};
template<class X, class Op>
X binary_fold( span<X> elems, Op op ) {
if (elems.empty()) return {};
if (elems.size() == 1) return elems.front();
auto lhs = binary_fold( elems.only_front( elems.size()/2 ), op );
auto rhs = binary_fold( elems.except_front( elems.size()/2 ), op );
return op(std::move(lhs), std::move(rhs));
}

Microsoft C++ Native Test Fails Assert::AreSame even when values are the same

I'm running a test with microsoft native unit testing framework (that comes with vs2019) and it fails with this message: Assert failed. Expected:<1> Actual:<1>
Here is the test code:
TEST_METHOD(memory_copy)
{
int ref[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int src[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int dest[10];
test::memory_copy<int>(src, dest, 10);
for (unsigned int i = 0; i < 10; i++)
{
Assert::AreSame(src[i], ref[i]);
Assert::AreSame(dest[i], ref[i]);
}
};
Note: memory_copy<>() copies memory from one pointer to another, just like std::memcpy()
Does anyone have an idea what may be the issue here?
Assert::AreSame() checks whether the inputs refer to the same object; it does not compare the values.
The implementation of the function (from CppUnitTestAssert.h) is as follows:
template<typename T> static void AreSame(const T& expected, const T& actual, const wchar_t* message = NULL, const __LineInfo* pLineInfo = NULL)
{
FailOnCondition(&expected == &actual, EQUALS_MESSAGE(expected, actual, message), pLineInfo);
}
What you can see here, is that it's comparing memory addresses, as opposed to the contents. Assert::AreEqual, on the other hand, compares the objects for equality.
template<typename T> static void AreEqual(const T& expected, const T& actual, const wchar_t* message = NULL, const __LineInfo* pLineInfo = NULL)
{
FailOnCondition(expected == actual, EQUALS_MESSAGE(expected, actual, message), pLineInfo);
}
It turns out that Assert::AreSame() doesn't do what I expected it to do. By changing it to Assert::AreEqual() I've solved the issue. More info here:
Microsoft Documentation on AreEqual()

Is it good practice to have boolean "recursiveCall" parameter in a function?

I have a function which calls itself, but to avoid infinite recursion when the function is calling itself I pass a boolean variable so it does not call itself again. However this also means someone using my code can use the function and pass it a true argument.
class Test
{
public:
static bool doCheck(int x, bool recursiveCall = false)
private:
int m_array {10, 5, 3, 25, 12, 0, -6};
int tracker = 0;
};
bool Test::doCheck(int x, bool recursiveCall)
{
if (m_array[tracker] > x)
{
//do stuff
++tracker;
return true;
}
else if (!recursiveCall)
{
// reset tracker
tracker = 0;
return doCheck(x, true);
}
return false;
}
int main()
{
Test::doCheck(2); // returns true, m_array[tracker] now equals 5
// The next call will go through the "else if" part which will reset the tracker
// and return false, if we didn't call the function as recursive it would call itself infinitely !
Test::doCheck(50);
return 0;
}
Edit: As requested I provided a better example. Of course we could perform the m_array[tracker] > x before calling doCheck() again but it means our check will be done twice, and it can be problematic if we check some things using a more complex algorithm
Is it good practice to do that?
No, that's a bad idea. Instead re-write your base case so that it will always stop on it's own.
Your example is never going to sensibly recurse, so it may as well be
void foo(int x)
{
if (x > 10)
{ /* Do stuff here */ }
}

Is it faster to use a bool and return later or call function and return immediately? C++

I have a question, which method would be theoretically faster to run? I have an extremely CPU intensive function, which doesn't run under certain conditions. Basically what I'm asking is, is it faster to just copy the calling code that uses many arguments many times in the same function, or is it faster to just use a bool to make the assembly smaller? Thanks
bool ShouldNotDoExpensiveFunction = false;
if (!somefunction())
{
ShouldNotDoExpensiveFunction = true;
}
else if (!somefunction2())
{
ShouldNotDoExpensiveFunction = true;
}
else if (!somefunction3())
{
ShouldNotDoExpensiveFunction = true;
}
else if (!somefunction4())
{
ShouldNotDoExpensiveFunction = true;
}
if (!ShouldNotDoExpensiveFunction)
{
return RunExpensiveFunction(1, 2, 3, 4, 5, 6, 7, 8, 9);
}
else
{
return RunInexpensiveFunction(1, 2);
}
or
if (!somefunction())
{
return RunInexpensiveFunction(1, 2);
}
else if (!somefunction2())
{
return RunInexpensiveFunction(1, 2);
}
else if (!somefunction3())
{
return RunInexpensiveFunction(1, 2);
}
else if (!somefunction4())
{
return RunInexpensiveFunction(1, 2);
}
else
{
return RunExpensiveFunction(1, 2, 3, 4, 5, 6, 7, 8, 9);
}
Both snippets are likely to have comparable performance. Since your function is very CPU intensive, the potential marginal difference between these approaches is very likely to be insignificant. A compiler might even generate identical assembly for each.
The former is superior to the latter not because of performance reasons, but because you avoid repeating the arguments thereby making the code less fragile to change.
There is an even better approach that doesn't require any repetition:
return somefunction() && somefunction2() && somefunction3() && somefunction4()
? RunExpensiveFunction(1, 2, 3, 4, 5, 6, 7, 8, 9)
: RunInexpensiveFunction(1, 2);