Reading List

The Selfish Gene
The Psychopath Test: A Journey Through the Madness Industry
Bad Science
The Feynman Lectures on Physics
The Theory of Everything: The Origin and Fate of the Universe


ifknot's favorite books »

Saturday, 22 February 2014

Building Blocks: C++11 Smart Pointers for the Logger Services and C++11 alias idioms

You can tell the logging services software was knocked up quickly... I completely forgot to use C++11 smart pointers[1] as part of the expressed RAII design pattern. Consequently the destructor was busy doing the pointer deleting idioms so familiar of C++03 (even if it did use the C++11 range based for loop to do it!). The changes also utilise the C++11 approach alias creation as replacement for typedef[2].

TL;DR The logging services code uses smart pointers now, but where it makes sense and not where it would make usage verbose and obfuscated.




This failure to implement the intended guarded approach to resources propagates back to the seralizor_policy class that has now done away with the public close() method in favour of having the destructor tidy up - as it should:

virtual ~serializor_policy() {
if (is_open()) {
do_close();
assert(is_closed());
}
}
Okay that's better.

So to set up the smart pointer usage I knocked up a couple of aliases to reduced code clutter and obfuscation:
using serializor_ptr = std::unique_ptr<io::serializor_policy<std::string>>;
using stamp_ptr = std::shared_ptr<log::stamp_policy>;
.
.
.
logger(const std::string name, std::initializer_list<stamp_ptr> stamp_list):
write_policy(new policy),
stamps(stamp_list) {
help_init(name);
}
.
.
.
virtual ~logger() {
//write_policy->close();
//delete write_policy;
//(auto stamp: stamps)
//delete(stamp);
}
.
.
.
serializor_ptr write_policy;
std::initializer_list<stamp_ptr> stamps;
Well that was easy!

Or was it...?

Because now in order to use logger the instantiation of the shared_ptr guarded stamp_policy(s) the code is now verbose and obfuscates the intention:

log::logger<io::console_serializor> clog("",
{std::shared_ptr<log::stamp_policy>(new log::line_number_stamp()),
std::shared_ptr<log::stamp_policy>(new log::line_number_stamp(10)),
std::shared_ptr<log::stamp_policy>(new log::unix_time_stamp())});
view raw yuck.cpp hosted with ❤ by GitHub
YUCK!

For the sake of saving a few lines in the destructor this is just not worth to the end user (me).

So with a quick change to the alias the job is fixed!

using stamp_ptr = log::stamp_policy*;
.
.
.
virtual ~logger() {
for (auto stamp: stamps)
delete(stamp);
}
view raw compromise.cpp hosted with ❤ by GitHub
References:
[1] Using C++11 Smart Pointers - Kieras (2013)
[2] What is the difference between 'typedef' and 'using' in C++11? (2012)


No comments:

Post a Comment