5 Replies - 898 Views - Last Post: 25 August 2014 - 06:24 AM Rate Topic: -----

#1 zerophase   User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 100
  • Joined: 07-May 13

unordered_map is behaving differently from expected.

Posted 24 August 2014 - 08:45 PM

Hey, I've been working through some sample code on TDD in C++. Most of the examples compile, minus a few things that VC++ doesn't like. (I'm chocking that up to different compilers.) The only issue I've had is when I check whether an unordered_map should be assigned a new value is always assigned to the key, despite it already being assigned. I've tried different equality checks to have the same issue each time.

The Code that leads to the the unordered_map:

class APortfolio : public Test
{
public:
	static const string SAMSUNG;

	static const date ArbitraryDate;

	Portfolio portfolio_;
	
	// How to code helper methods that abstract common functionality
	// and allow for updatable tests, without having to change old tests
	// to reflect changes to the class under test.
	void Purchase(const string &symbol, int shareCount,
		const date &transactionDate = APortfolio::ArbitraryDate)
	{
		portfolio_.Purchase(symbol, shareCount, transactionDate);
	}

	void Sell(const string &symbol, int shareCount,
		const date &transactionDate = APortfolio::ArbitraryDate)
	{
		portfolio_.Sell(symbol, shareCount, transactionDate);
	}

	void ASSERT_PURCHASE(PurchaseRecord &purchase, int shareCount,
		const date &transactionDate)
	{
		ASSERT_THAT(purchase.ShareCount, Eq(shareCount));
		ASSERT_THAT(purchase.Date, Eq(transactionDate));
	}
};

const string APortfolio::SAMSUNG("SSNLF");

const date APortfolio::ArbitraryDate(2014, Sep, 5);

TEST_F(APortfolio, ReducesShareCountOfSymboleOnSell)
{
	Purchase(SAMSUNG, 30);

	Sell(SAMSUNG, 13);

	ASSERT_THAT(portfolio_.ShareCount(SAMSUNG), Eq(30u - 13));
}


And the methods that handle the generation and assignment for each key:

void Portfolio::addPurchaseRecord(const string &symbol, int shareCount, const date &date)
{
	if (!containsSymbol(symbol));
		initializePurchaseRecords(symbol);
	add(symbol, { shareCount, date });
}

bool Portfolio::containsSymbol(const std::string &symbol) const
{
	return holdings_.find(symbol) == holdings_.end();
}

void Portfolio::initializePurchaseRecords(const string &symbol)
{
	holdings_[symbol] = Holding();
}

void Portfolio::add(const string &symbol, PurchaseRecord &&record)
{
	holdings_[symbol].Add(record);
}


When
Purchase()
and
Sell()
are called the holdings_ unordered_map are reinitialized each time. All of the sample code for checking for a key in an unordered_map, I've found on Stack Overflow, matches what I have. Any idea what's going on here?

This post has been edited by zerophase: 24 August 2014 - 08:48 PM


Is This A Good Question/Topic? 0
  • +

Replies To: unordered_map is behaving differently from expected.

#2 Skydiver   User is offline

  • Code herder
  • member icon

Reputation: 7915
  • View blog
  • Posts: 26,425
  • Joined: 05-May 12

Re: unordered_map is behaving differently from expected.

Posted 24 August 2014 - 09:18 PM

The sense of your check in Portfolio::containsSymbol() seems to be wrong. If the symbol is found, why would find() return the the end() iterator value? The documentation claims that it will only return end() when a match is not found.
Was This Post Helpful? 0
  • +
  • -

#3 zerophase   User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 100
  • Joined: 07-May 13

Re: unordered_map is behaving differently from expected.

Posted 24 August 2014 - 10:11 PM

I thought

Quote

end()
returns an iterator past the last key in the collection, and using it with

Quote

find()
it's possible to check whether a key is in the collection or not.

According to this post
find()
and

Quote

end()
can be used to check for whether keys are in the unordered_map or not:

if (my_hash_map.find(non-existent key) == my_hash_map.end())


In Modern C++ Programming with Test-Driven Development the example code is written like this:

return my_hash_map.find(key) != my_hash_map.end()


with the calling block checking for the inverse of that equality check.

I've tried inversing the equality check for the key and the calling if statement, and even tried different combinations of both getting me the same result each time. despite how the check is setup for whether the key already exists, it always initializes the value again.
Was This Post Helpful? 0
  • +
  • -

#4 #define   User is offline

  • Cannot compute!
  • member icon

Reputation: 1868
  • View blog
  • Posts: 6,763
  • Joined: 19-February 09

Re: unordered_map is behaving differently from expected.

Posted 24 August 2014 - 10:32 PM

Hi, this suddenly jumped out at me :-

03	if (!containsSymbol(symbol)); //<- semicolon
04		initializePurchaseRecords(symbol);



.

This post has been edited by #define: 25 August 2014 - 04:54 AM

Was This Post Helpful? 1
  • +
  • -

#5 zerophase   User is offline

  • D.I.C Head

Reputation: 1
  • View blog
  • Posts: 100
  • Joined: 07-May 13

Re: unordered_map is behaving differently from expected.

Posted 24 August 2014 - 10:39 PM

Thanks, I've been staring at that piece of code for an hour thinking Microsoft isn't completely adherent to the standard in their implementation of C++. I can't believe I didn't see that typo. My eyes must be going.
Was This Post Helpful? 0
  • +
  • -

#6 vividexstance   User is offline

  • Tiocfaidh ár lá
  • member icon

Reputation: 794
  • View blog
  • Posts: 2,880
  • Joined: 31-December 10

Re: unordered_map is behaving differently from expected.

Posted 25 August 2014 - 06:24 AM

If you just want to know if a key is in the map but don't need an iterator to it, then why not use the unordered_map::count() member function?
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1