I am working on a personal project to familiarize myself with C++11 and Boost.
I have a inheritance relationship with a UrlExtractor
base class, with a TagUrlExtractor
derived class and a CompoundExtractor
derived class. A CompoundExtractor
can contain any number of UrlExtractors
, thus implementing the composite pattern.
I am curious what the method signature for CompositeExtractor.addExtractor
should look like. Since I'm dealing with a polymorphic type, I am forced to work with pointers (or references). I want to use the new smart pointers, specifically shared_ptr
.
I tried writing the addExtractor
member function like this:
void addExtractor(shared_ptr<UrlExtractor> extractor);
However, I get a compile error if I try to write:
compound.addExtractor(new TagUrlExtractor());
The issue is that it would take two implicit conversions to create a shared_ptr<UrlExtractor>
: one to the UrlExtractor
base class and second to the shared_ptr
.
I could call the function like this:
compound.addExtractor(shared_ptr<UrlExtractor>(new TagUrlExtractor));
However, this is very verbose. How is this situation handled normally?
The issue is that it would take two implicit conversions to create a shared_ptr: one to the UrlExtractor base class and second to the shared_ptr
That's not the issue: the issue is that the constructor of shared_ptr
that accepts a raw pointer is marked as explicit
, so it can't be used in a copy-initialization context (function parameters are copy-initialized, as specified by § 8.5/15).
You could (and actually, should) use std::make_shared
:
compound.addExtractor(std::make_shared<TagUrlExtractor>());
std::make_shared()
has the advantage of being exception-safe and performing one dynamic allocation less than when you are initializing a shared pointer from a new
expression (also see this Q&A on StackOverflow).