Can I use boost::make_shared with a private constructor? - c++

Consider the following:
class DirectoryIterator;
namespace detail {
class FileDataProxy;
class DirectoryIteratorImpl
{
friend class DirectoryIterator;
friend class FileDataProxy;
WIN32_FIND_DATAW currentData;
HANDLE hFind;
std::wstring root;
DirectoryIteratorImpl();
explicit DirectoryIteratorImpl(const std::wstring& pathSpec);
void increment();
bool equal(const DirectoryIteratorImpl& other) const;
public:
~DirectoryIteratorImpl() {};
};
class FileDataProxy //Serves as a proxy to the WIN32_FIND_DATA struture inside the iterator.
{
friend class DirectoryIterator;
boost::shared_ptr<DirectoryIteratorImpl> iteratorSource;
FileDataProxy(boost::shared_ptr<DirectoryIteratorImpl> parent) : iteratorSource(parent) {};
public:
std::wstring GetFolderPath() const {
return iteratorSource->root;
}
};
}
class DirectoryIterator : public boost::iterator_facade<DirectoryIterator, detail::FileDataProxy, std::input_iterator_tag>
{
friend class boost::iterator_core_access;
boost::shared_ptr<detail::DirectoryIteratorImpl> impl;
void increment() {
impl->increment();
};
bool equal(const DirectoryIterator& other) const {
return impl->equal(*other.impl);
};
detail::FileDataProxy dereference() const {
return detail::FileDataProxy(impl);
};
public:
DirectoryIterator() {
impl = boost::make_shared<detail::DirectoryIteratorImpl>();
};
};
It seems like DirectoryIterator should be able to call boost::make_shared<DirectoryIteratorImpl>, because it is a friend of DirectoryIteratorImpl. However, this code fails to compile because the constructor for DirectoryIteratorImpl is private.
Since this class is an internal implementation detail that clients of DirectoryIterator should never touch, it would be nice if I could keep the constructor private.
Is this my fundamental misunderstanding around make_shared or do I need to mark some sort of boost piece as friend in order for the call to compile?

You will indeed need to make some boost pieces friend for this. Basically make_shared is calling the constructor and the fact that this is done from within a friend function does not matter for the compiler.
The good news though is that make_shared is calling the constructor, not any other piece. So just making make_shared friend would work... However it means that anyone could then create a shared_ptr<DirectoryIteratorImpl>...

Is there a good reason not to use the good old shared_ptr constructor? (If there is one, you might want to take a look at the make_shared implementation and do it)
DirectoryIterator()
: impl( new detail::DirectoryIteratorImpl() )
{}
This way the call to the constructor is made from the DirectoryIterator class that is already a friend of DirectoryIteratorImpl without opening the door for all other code.

You can split your class into interface part and implementation part.
The interface part is made public, and the implementation part can have public constructors.
However, that means you have to use virtual inheritance.

Related

Overloaded operator= to switch between template types

I have a template class that multiple classes are inheriting from to basically make some user-friendly builders, hiding the functions that are not required on different builders, while following DRY.
However, I'm having trouble switching between the builder types. I'd prefer to use the operator= to switch without hassle and have the following code.
template<class T> class BuilderFunctions
{
protected:
std::string text;
public:
template<class Other>
BuilderFunctions<T>& operator=(const Other& other);
};
template <class T>
template <class Other>
BuilderFunctions<T>& BuilderFunctions<T>::operator=(const Other& other)
{
// yes, I need same object protection
text = other.text;
return *this;
}
Classes
class BuilderGenericList : public BuilderFunctions<BuilderGenericList>
{
public:
BuilderGenericList() = default;
};
// Build configuration details
class BuilderRootList : public BuilderFunctions<BuilderRootList>
{
private:
// I'll delete the functions I don't want accessed here
public:
BuilderRootList() = default;
};
Code that says no
// Real world you'd build the root first and switch out to another builder or be using a prototype to seed another builder
BuilderRootList cmakeRoot;
BuilderGenericList list;
// Separate to make sure it's not trying to use cop constructor
list = cmakeRoot;
Except I might be doing something I shouldn't be doing with template classes, although others seem to have success with templates in the operators, so assume possible, and I'm making some kind of mistake.
More info: The error I get is:
Error C2679 binary '=': no operator found which takes a right-hand operand
of type 'BuilderRootList' (or there is no acceptable conversion)
So It's definitely looking for my operator=, it's just not generating one from the template
When you do the template inheritance, you have to be explicit in case of base classes members. More read:
Why do I have to access template base class members through the this pointer?
Derived template-class access to base-class member-data
Accessing base member functions in class derived from template class
In your case, the members text, and operator=, can be brought via using declaration.
class BuilderGenericList : public BuilderFunctions<BuilderGenericList>
{
public:
BuilderGenericList() = default;
using BuilderFunctions<BuilderGenericList>::text;
using BuilderFunctions<BuilderGenericList>::operator=;
// ... so on, other members from base if needed!
};
// Build configuration details
class BuilderRootList : public BuilderFunctions<BuilderRootList>
{
public:
BuilderRootList() = default;
using BuilderFunctions<BuilderRootList>::text;
using BuilderFunctions<BuilderRootList>::operator=;
// ... so on, other members from base if needed!
};
Live Demo
Note that, this will make the memberusing BuilderFunctions<BuilderGenericList>::text public, if this is not what wanted, consider the suggestion by #Jarod42 in other answer.
BuilderFunctions<T1> cannot access private/protected member of BuilderFunctions<T2> (with T1 != T2): add accessor, or make them friend.
in addition, you also have to put using for operator=:
template<class T>
class BuilderFunctions
{
template <typename U> friend class BuilderFunctions;
protected:
std::string text;
public:
template<class Other>
BuilderFunctions<T>& operator=(const Other& other);
};
template <class T>
template <class Other>
BuilderFunctions<T>& BuilderFunctions<T>::operator=(const Other& other)
{
//yes, I need same object protection
text= other.text;
return *this;
}
class BuilderGenericList : public BuilderFunctions<int>{
public:
using BuilderFunctions<int>::operator=;
BuilderGenericList() = default;
};
//Build configuration details
class BuilderRootList : public BuilderFunctions<float>
{
private:
//I'll delete the functions I don't want accessed here
public:
using BuilderFunctions<float>::operator=;
BuilderRootList() = default;
};
Demo

Pimpl idiom as template base class

I'm currently researching the pimpl idiom and there are very nice tutorials how it could be implement (e.g. here). But i have never seen it implemented as a base template class like this:
#ifndef PIMPL_H
#define PIMPL_H
template <class T>
class Pimpl
{
public:
explicit Pimpl();
explicit Pimpl(T *ptr);
virtual ~Pimpl() = 0;
Pimpl(const Pimpl<T> &other);
Pimpl &operator=(const Pimpl<T> &other);
protected:
T *d_ptr;
};
template<class T>
Pimpl<T>::Pimpl() : d_ptr(new T)
{
}
template<class T>
Pimpl<T>::Pimpl(T *ptr) : d_ptr(ptr)
{
}
template<class T>
Pimpl<T>::~Pimpl()
{
delete d_ptr;
d_ptr = 0;
}
template<class T>
Pimpl<T>::Pimpl(const Pimpl<T> &other) : d_ptr(new T(*other.d_ptr))
{
}
template<class T>
Pimpl<T> &Pimpl<T>::operator=(const Pimpl<T> &other)
{
if (this != &other) {
delete d_ptr;
d_ptr = new T(*other.d_ptr);
}
return *this;
}
#endif // PIMPL_H
Which then could be used in any class you like to pimpl:
#ifndef OBJECT_H
#define OBJECT_H
#include "pimpl.h"
class ObjectPrivate;
class Object : public Pimpl<ObjectPrivate>
{
public:
Object();
virtual ~Object();
/* ... */
};
#endif // OBJECT_H
Currently i'm using it in a small example project (build as a shared library) and the only problem i had, was that MSVC warns about the missing destructor for ObjectPrivate (see C4150). This warning only occurs, because ObjectPrivate is forward declared and therefore not visible to the delete operator in Pimpl::~Pimpl() at compile time.
Does anyone see any sort of problems with this approach? :-)
So there is a now a final version based on the discussion below on GitHub (big thanks to StoryTeller). The repository also contains a simple usage example.
Yes, there are several problems, as I see it.
Your class is essentially a mixin. It's not about dynamic polymorphism, so no-one is ever going to call delete on a pointer to Pimpl<ObjectPrivate>. Drop the virtual destructor. It's introducing overhead that's never going to be required. What you want is static polymorphism only.
You allocate the object with new and release with delete. I won't use your template, because that allocation scheme isn't always appropriate in my applications. You must give a way to customize the allocation scheme in order to make your class actually useful.
Your assignment operator isn't exception safe. If the constructor for T throws, you lose the previously saved data. IMO it's better in this case to use the copy and swap idiom.
The solution to (1) and (2) is to add more template parameters, where the first is for the CRTP. This will allow you to push operations you aren't aware of how to do, onto the class that inherits your mixin. It can override them by defining its own make, unmake and clone. And those will all be bound statically.
template <class Handle, class Impl>
class Pimpl
{
private:
Impl* _make() const
{ return ((Handle const*)this)->make(); }
void _unmake(Impl *p) const
{ ((Handle const*)this)->unmake(p); }
Impl* _clone(Impl *p) const
{ return ((Handle const*)this)->clone(p); }
void swap(Pimpl &other) {
Impl *temp = d_ptr;
d_ptr = other.d_ptr;
other.d_ptr = temp;
}
public:
explicit Pimpl();
~Pimpl();
Pimpl(const Pimpl &other);
Pimpl &operator=(const Pimpl &other);
// fall-backs
static Impl* make() { return new Impl; }
static void unmake(Impl* p) { delete p; }
static Impl* clone(Impl* p) { return new Impl(*p); }
protected:
Impl *d_ptr;
};
template<class Handle, class Impl>
Pimpl<Handle, Impl>::Pimpl() :
d_ptr(_make())
{
}
template<class Handle, class Impl>
Pimpl<Handle, Impl>::~Pimpl()
{
_unmake(d_ptr);
d_ptr = 0;
}
template<class Handle, class Impl>
Pimpl<Handle, Impl>::Pimpl(const Pimpl &other) :
d_ptr(_clone(other.d_ptr))
{
}
template<class Handle, class Impl>
Pimpl<Handle, Impl> &Pimpl<Handle, Impl>::operator=(const Pimpl &other)
{
Pimpl copy(other);
swap(copy);
return *this;
}
Live Example
Now your header can compile cleanly. So long as the destructor for Object isn't defined inline. When it's inline the compiler must instantiate the destructor of the template wherever object.h is included.
If it's defined in a cpp file, after the definition of ObjectPrivate, then the instantiation of ~Pimpl will see the full definition of the private parts.
Further ideas for improvement:
Make the special members protected. It's only the derived Handle class that's supposed to call them, after all.
Add support for move semantics.
But i have never seen it implemented as a base template class
Vladimir Batov did it: https://github.com/yet-another-user/pimpl
Does anyone see any sort of problems with this approach?
You need to take the warning seriously. If your ObjectPrivate actually has a non-trivial destructor (which is as easy as containing a std::string member), you have undefined behavior, and the destructor probably won't get called.
This typically suggests that for some reason, the destructor is instantiated in the wrong place. Make sure that all definitions of all constructors and destructors of the derived class are placed after the full definition of ObjectPrivate. This includes the implicit copy and move constructors, which are probably what triggers the warning in your example code. Yes, this means you have to explicitly declare these special functions (and as a consequence, also the copy and move assignment operators if you want them), but at least you can use a defaulted definition.
I don't know if Vlad's library has the same problem.
Also, nulling out pointers in a destructor is pointless and will probably just get optimized away by some modern compilers.
Modern version that I'm using:
///////////////////////////////
// Header File
template <typename impl_t>
class Pimpl {
public:
Pimpl() = default;
virtual ~Pimpl() = default;
Pimpl(std::shared_ptr<impl_t> handle) : handle(handle) {}
std::shared_ptr<impl_t>
get_handle() const {
return handle;
}
protected:
std::shared_ptr<impl_t> handle;
};
class object_impl;
class object : public Pimpl<object_impl> {
/* whatever constructors you want*/
public:
object(int x);
}
///////////////////////////////
// Cpp File
class object_impl {
public:
object_impl(int x) : x_(x) {}
private:
int x_;
}
object::object(int x) : Pimpl(std::make_shared<object_impl>(x)) {}

STL: Initializing a container with an unconstructed stateful comparator

This has been running through my mind as a possible solution to an issue, however as it is a fairly obvious technical violation of something in C++, I wanted to know how likely to it is to fail, whether there is another fairly obvious approach, etc. I'm hoping this doesn't get into a flamewar about undefined behavior, but considering the topic I do expect a little bit.
This is not the code I'm writing, I'm hoping it's not too simplified to not describe what I am attempting to do.
class Code
{
public:
bool read(short slot, short& val);
bool read(short slot, long& val);
bool read(short slot, double& val);
// etc
protected:
unsigned char* m_data;
};
typedef boost::shared_ptr<Code> CodePtr;
class SortedBase
{
protected:
class Sorter : public std::binary_function<CodePtr,CodePtr,bool>
{
protected:
inline Sorter() {}
virtual ~Sorter() {}
public:
virtual bool operator()(CodePtr left, CodePtr right) PURE;
};
inline SortedBase(Sorter* s):m_codeList(s) {}
typedef std::set<CodePtr,Sorter> TSortedCode;
TSortedCode m_codeList;
public:
virtual ~SortedBase() {}
void fetch(); // populates m_codeList
};
template<class SORT1, class SORT2, class SORT3, class SORT4, class SORT5>
class SortedObject5 : public SortedBase
{
public:
SortedObject5():SortedBase(m_sorter),m_sorter(this) {}
something_interesting find(SORT1 val1, SORT2 val2, SORT3 val3, SORT4 val4, SORT5 val5);
protected:
typedef SortedObject5<SORT1,SORT2,SORT3,SORT4,SORT5> my_class;
class MySorter : public Sorter
{
public:
MySorter(const my_class& parent):m_parent(parent) {}
virtual operator()(CodePtr left, CodePtr right);
protected:
const my_class& m_parent;
}
MySorter m_sorter;
};
The intent here
I've often found when writing template classes that having a non-template base class with as much of the factored logic as possible is useful to both have some common class other code can reference and reduce the amount of code duplication, especially when making five different versions of the same class with different numbers of template parameters.
In this case the CodePtr is generated elsewhere in the code (although I did write it) and I would like to find elements based on an arbitrary number of arbitrary datatypes. I considered a std::multimap at first but the key would end up being a wrapper to (or a copy of a significant chunk of) the CodePtr again.
The problem
I am passing the stateful sorter functor SortedObject5<>::my_sorter to the constructor of SortedBase::m_codeList. However because the stateful sorter being in a sublcass, is fairly obviously not constructed at the point that the STL set is constructed.
I'm wondering if this is an issue if I don't make any inserts or searches in m_codeList from either constructor.
Stateful sorter disclaimer
I formally ASSERT() that the rules used by any stateful sort functor will change only while either the STL containers it controls are empty or will be clear()ed shortly afterwards.
The std::set<CodePtr,Sorter> object stores an instance of Sorter by value so when you construct it with a Sorter* (did you mean that to be a reference not a pointer?) it will slice the object and only keep the base part.
That means the Sorter copy constructor will run and make a copy of an uninitialized object. Undefined behaviour ensues.
That's assuming you can even create an instance of Sorter, if it's an abstract type you won't be able to (I don't know what your PURE does but I assume you're making the function pure virtual)
#Angew's comment suggest a good approach, the base from member idiom will allow you to ensure the m_sorter object is initialized first, which is part of the problem. That doesn't help the issue of slicing though, to solve that you'd need some wrapper around the sorter e.g.
typedef std::function<bool(const CodePtr&,const CodePtr&)> SorterFunc;
typedef std::set<CodePtr, SorterFunc> TSortedCode;
And then pass the wrapper to the set constructor:
inline SortedBase(SorterFunc s) : m_codeList(s) {}
If you construct the std::function from the derived type it won't be sliced. It will be copied though, but you can prevent that by using a reference wrapper:
SortedObject5() : BaseFrommember(this), SortedBase(SorterFunc(std::ref(m_sorter))) { }
Where m_sorter is already initialized, because it is stored in the BaseFromMember base class, using the base-from-member idiom.
This:
creates the m_sorter first so you don't do anything with an uninitialized object
passes it by reference to a SorterFunc object
uses a copy of that SorterFunc (still holding a reference to m_sorter) as the comparision function for the std::set
If you don't want to use the base-from-member idiom then it's still easy to avoid the undefined behaviour of your original code, just default construct the set (instead of passing it an uninitialized object) then assign a new value to it before you start populating it:
SortedObject5() : m_sorter(this)
{
this->m_codeList = TSortedCode(SorterFunc(boost::ref(m_sorter)));
}
No new base classes, no extra templates, no undefined behaviour.
Here's the working code in full:
class SortedBase
{
protected:
class Sorter : public std::binary_function<CodePtr,CodePtr,bool>
{
protected:
Sorter() {}
virtual ~Sorter() {}
public:
virtual bool operator()(const CodePtr& left, const CodePtr& right) = 0;
};
typedef boost::function<bool(const CodePtr&, const CodePtr&)> SorterFunc;
typedef std::set<CodePtr,SorterFunc> TSortedCode;
TSortedCode m_codeList;
public:
virtual ~SortedBase() {}
void fetch(); // populates m_codeList
};
template<class SORT1, class SORT2, class SORT3, class SORT4, class SORT5>
class SortedObject5 : public SortedBase
{
public:
SortedObject5() : m_sorter(*this)
{
this->m_codeList = TSortedCode(SorterFunc(boost::ref(m_sorter)));
}
protected:
typedef SortedObject5<SORT1,SORT2,SORT3,SORT4,SORT5> my_class;
class MySorter : public Sorter
{
public:
MySorter(const my_class& parent):m_parent(parent) {}
virtual bool operator()(const CodePtr& left, const CodePtr& right);
protected:
const my_class& m_parent;
};
MySorter m_sorter;
};

An alternative to friend when overloading >>?

In the situation below, is there any alternative to using friend? I would like to preserve all functionality of overloading the operator >>. I do not want to have public accessors in the reader class.
struct FunctorBase
{
virtual ~FunctorBase(){}
virtual void operator()(Reader &reader) const = 0;
};
//does specific stuff related to the purpose of end.
struct end : FunctorBase
{
void operator()(Reader &reader) const
{
//work with private data in reader
}
};
class Reader
{
friend class end; //I want to get rid of this if possible without losing the
//functionality of operator>> or providing accessors
Reader& operator>>(const FunctorBase &functor)
{
functor(*this);
return *this;
}
};
Any help is appreciated.
EDIT: I plan on having multiple derived classes of FunctorBase, thus multiple friend declarations. Isn't this abusing the concept of friend?
I guess the best solution depends on what end has to do with Reader.
Did you think about a base class with private inheritance (kind of interface)? You'll expose only what you need and it won't be accesible to others. Just as example:
class ReaderInterface
{
public:
void method()
{
}
};
// This is your "end" class, derived from FunctorBase,
// the consumer of ReaderInterface
class Consumer
{
public:
Consumer(ReaderInterface readerInterface)
{
readerInterface.method();
}
};
class Reader : private ReaderInterface
{
public:
void test()
{
Consumer consumer(*this);
}
};

PIMPL problem: How to have multiple interfaces to the impl w/o code duplication

I have this pimpl design where the implementation classes are polymorphic but the interfaces are supposed to just contain a pointer, making them polymorphic somewhat defeats the purpose of the design.
So I create my Impl and Intf base classes to provide reference counting. And then the user can create their implementations. An example:
class Impl {
mutable int _ref;
public:
Impl() : _ref(0) {}
virtual ~Impl() {}
int addRef() const { return ++_ref; }
int decRef() const { return --_ref; }
};
template <typename TImpl>
class Intf {
TImpl* impl;
public:
Intf(TImpl* t = 0) : impl(0) {}
Intf(const Intf& other) : impl(other.impl) { if (impl) impl->addRef(); }
Intf& operator=(const Intf& other) {
if (other.impl) other.impl->addRef();
if (impl && impl->decRef() <= 0) delete impl;
impl = other.impl;
}
~Intf() { if (impl && impl->decRef() <= 0) delete impl; }
protected:
TImpl* GetImpl() const { return impl; }
void SetImpl(... //etc
};
class ShapeImpl : public Impl {
public:
virtual void draw() = 0;
};
class Shape : public Intf<ShapeImpl> {
public:
Shape(ShapeImpl* i) : Intf<ShapeImpl>(i) {}
void draw() {
ShapeImpl* i = GetImpl();
if (i) i->draw();
}
};
class TriangleImpl : public ShapeImpl {
public:
void draw();
};
class PolygonImpl : public ShapeImpl {
public:
void draw();
void addSegment(Point a, Point b);
};
Here is where have the issue. There are two possible declaration for class Polygon:
class Polygon1 : public Intf<PolygonImpl> {
public:
void draw() {
PolygonImpl* i = GetImpl();
if (i) i->draw();
}
void addSegment(Point a, Point b) {
PolygonImpl* i = GetImpl();
if (i) i->addSegment(a,b);
}
};
class Polygon2 : public Shape {
void addSegment(Point a, Point b) {
ShapeImpl* i = GetImpl();
if (i) dynamic_cast<Polygon*>(i)->addSegment(a,b);
}
}
In the Polygon1, I have rewrite the code for draw because I have not inherited it. In Polygon2 I need ugly dynamic casts because GetImpl() doesn't know about PolygonImpl. What I would like to do is something like this:
template <typename TImpl>
struct Shape_Interface {
void draw() {
TImpl* i = GetImpl();
if (i) i->draw();
}
};
template <typename TImpl>
struct Polygon_Interface : public Shape_Interface<Timpl> {
void addSegment(Point a, Point b) { ... }
};
class Shape : public TIntf<ShapeImpl>, public Shape_Interface<ShapeImpl> {...};
class Polygon : public TIntf<PolygonImpl>, public Polygon_Interface<PolygonImpl> {
public:
Polygon(PolygonImpl* i) : TIntf<PolygonImpl>(i) {}
};
But of course there's a problem here. I can't access GetImpl() from the Interface classes unless I derive them from Intf. And if I do that, I need to make Intf virtual everywhere it appears.
template <typename TImpl>
class PolygonInterface : public virtual Intf<TImpl> { ... };
class Polygon : public virtual Intf<PolygonImpl>, public PolygonInterface { ... }
OR I can store a TImpl*& in each Interface and construct them with a reference to the base Intf::impl. But that just means I have a pointer pointing back into myself for every interface included.
template <typename TImpl>
class PolygonInterface {
TImpl*& impl;
public:
PolygonInterface(TImpl*& i) : impl(i) {}
...};
Both of these solutions bloat the Intf class, add an extra dereference, and basically provide no benefit over straight polymorphism.
So, the question is, is there a third way, that I've missed that would solve this issue besides just duplicating the code everywhere (with its maintenance issues)?
TOTALLY SHOULD, BUT DOESN'T WORK: I wish there were base classes unions that just overlaid the class layouts and, for polymorphic classes, required that they have the exact same vtable layout. Then both Intf and ShapeInterface would each declare a single T* element and access it identically:
class Shape : public union Intf<ShapeImpl>, public union ShapeInterface<ShapeImpl> {};
I should note that your Impl class is nothing more than the reimplementation of a shared_ptr without the thread safety and all those cast bonuses.
Pimpl is nothing but a technic to avoid needless compile-time dependencies.
You do not need to actually know how a class is implemented to inherit from it. It would defeat the purpose of encapsulation (though your compiler does...).
So... I think that you are not trying to use Pimpl here. I would rather think this is a kind of Proxy patterns, since apparently:
Polygon1 numberOne;
Polygon2 numberTwo = numberOne;
numberTwo.changeData(); // affects data from numberOne too
// since they point to the same pointer!!
If you want to hide implementation details
Use Pimpl, but the real one, it means copying in depth during copy construction and assignment rather than just passing the pointer around (whether ref-counted or not, though ref-counted is preferable of course :) ).
If you want a proxy class
Just use a plain shared_ptr.
For inheritance
It does not matter, when you inherit from a class, how its private members are implemented. So just inherit from it.
If you want to add some new private members (usual case), then:
struct DerivedImpl;
class Derived: public Base // Base implemented with a Pimpl
{
public:
private:
std::shared_ptr<DerivedImpl> _data;
};
There is not much difference with classic implementation, as you can see, just that there is a pointer in lieu of a bunch of data.
BEWARE
If you forward declare DerivedImpl (which is the goal of Pimpl), then the destructor automatically generated by the compiler is... wrong.
The problem is that in order to generate the code for the destructor, the compiler needs the definition of DerivedImpl (ie: a complete type) in order to know how to destroy it, since a call to delete is hidden in the bowels of shared_ptr. However it may only generate a warning at compilation time (but you'll have a memory leak).
Furthermore, if you want an in-depth copy (rather than a shallow one, which consists in the copy and the original both pointing to the same DerivedImpl instance), you will also have to define manually the copy-constructor AND the assignment operator.
You may decide to create a better class that shared_ptr which will have deep-copy semantics (which could be called member_ptr as in cryptopp, or just Pimpl ;) ). This introduce a subtle bug though: while the code generated for the copy-constructor and the assignement operator could be thought of as correct, they are not, since once again you need a complete type (and thus the definition of DerivedImpl), so you will have to write them manually.
This is painful... and I'm sorry for you.
EDIT: Let's have a Shape discussion.
// Shape.h
namespace detail { class ShapeImpl; }
class Shape
{
public:
virtual void draw(Board& ioBoard) const = 0;
private:
detail::ShapeImpl* m_impl;
}; // class Shape
// Rectangle.h
namespace detail { class RectangleImpl; }
class Rectangle: public Shape
{
public:
virtual void draw(Board& ioBoard) const;
size_t getWidth() const;
size_t getHeight() const;
private:
detail::RectangleImpl* m_impl;
}; // class Rectangle
// Circle.h
namespace detail { class CircleImpl; }
class Circle: public Shape
{
public:
virtual void draw(Board& ioBoard) const;
size_t getDiameter() const;
private:
detail::CircleImpl* m_impl;
}; // class Circle
You see: neither Circle nor Rectangle care if Shape uses Pimpl or not, as its name implies, Pimpl is an implementation detail, something private that is not shared with the descendants of the class.
And as I explained, both Circle and Rectangle use Pimpl too, each with their own 'implementation class' (which can be nothing more than a simple struct with no method by the way).
I think you were right in that I didn't understand your question initially.
I think you're trying to force a square shape into a round hole... it don't quite fit C++.
You can force that your container holds pointers to objects of a given base-layout, and then allow objects of arbitrary composition to be actually pointed to from there, assuming that you as a programmer only actually place objects that in fact have identical memory layouts (member-data - there's no such thing as member-function-layout for a class unless it has virtuals, which you wish to avoid).
std::vector< boost::shared_ptr<IShape> > shapes;
NOTE at the absolute MINIMUM, you must still have a virtual destructor defined in IShape, or object deletion is going to fail miserably
And you could have classes which all take a pointer to a common implementation core, so that all compositions can be initialized with the element that they share (or it could be done statically as a template via pointer - the shared data).
But the thing is, if I try to create an example, I fall flat the second I try to consider: what is the data shared by all shapes? I suppose you could have a vector of Points, which then could be as large or small as any shape required. But even so, Draw() is truly polymorphic, it isn't an implementation that can possibly be shared by multiple types - it has to be customized for various classifications of shapes. i.e. a circle and a polygon cannot possibly share the same Draw(). And without a vtable (or some other dynamic function pointer construct), you cannot vary the function called from some common implementation or client.
Your first set of code is full of confusing constructs. Maybe you can add a new, simplified example that PURELY shows - in a more realistic way - what you're trying to do (and ignore the fact that C++ doesn't have the mechanics you want - just demonstrate what your mechanic should look like).
To my mind, I just don't get the actual practical application, unless you're tyring to do something like the following:
Take a COM class, which inherits from two other COM Interfaces:
class MyShellBrowserDialog : public IShellBrowser, public ICommDlgBrowser
{
...
};
And now I have a diamond inheritence pattern: IShellBrowser inherits ultimately from IUnknown, as does ICommDlgBrowser. But it seems incredibly silly to have to write my own IUnknown:AddRef and IUnknown::Release implementation, which is a highly standard implementation, because there's no way to cause the compiler to let another inherited class supply the missing virtual functions for IShellBrowser and/or ICommDlgBrowser.
i.e., I end up having to:
class MyShellBrowserDialog : public IShellBrowser, public ICommDlgBrowser
{
public:
virtual ULONG STDMETHODCALLTYPE AddRef(void) { return ++m_refcount; }
virtual ULONG STDMETHODCALLTYPE Release(void) { return --m_refcount; }
...
}
because there's no way I know of to "inherit" or "inject" those function implementations into MyShellBrowserDialog from anywhere else which actually fill-in the needed virtual member function for either IShellBrowser or ICommDlgBrowser.
I can, if the implementations were more complex, manually link up the vtable to an inherited implementor if I wished:
class IUnknownMixin
{
ULONG m_refcount;
protected:
IUnknonwMixin() : m_refcount(0) {}
ULONG AddRef(void) { return ++m_refcount; } // NOTE: not virutal
ULONG Release(void) { return --m_refcount; } // NOTE: not virutal
};
class MyShellBrowserDialog : public IShellBrowser, public ICommDlgBrowser, private IUnknownMixin
{
public:
virtual ULONG STDMETHODCALLTYPE AddRef(void) { return IUnknownMixin::AddRef(); }
virtual ULONG STDMETHODCALLTYPE Release(void) { return IUnknownMixin::Release(); }
...
}
And if I needed the mix-in to actually refer to the most-derived class to interact with it, I could add a template parameter to IUnknownMixin, to give it access to myself.
But what common elements could my class have or benefit by that IUnknownMixin couldn't itself supply?
What common elements could any composite class have that various mixins would want to have access to, which they needed to derive from themselves? Just have the mixins take a type parameter and access that. If its instance data in the most derived, then you have something like:
template <class T>
class IUnknownMixin
{
T & const m_outter;
protected:
IUnknonwMixin(T & outter) : m_outter(outter) {}
// note: T must have a member m_refcount
ULONG AddRef(void) { return ++m_outter.m_refcount; } // NOTE: not virtual
ULONG Release(void) { return --m_outter.m_refcount; } // NOTE: not virtual
};
Ultimately your question remains somewhat confusing to me. Perhaps you could create that example that shows your preferred-natural-syntax that accomplishes something clearly, as I just don't see that in your initial post, and I can't seem to sleuth it out from toying with these ideas myself.
I have seen lots of solutions to this basic conundrum: polymorphism + variation in interfaces.
One basic approach is to provide a way to query for extended interfaces - so you have something along the lines of COM programming under Windows:
const unsigned IType_IShape = 1;
class IShape
{
public:
virtual ~IShape() {} // ensure all subclasses are destroyed polymorphically!
virtual bool isa(unsigned type) const { return type == IType_IShape; }
virtual void Draw() = 0;
virtual void Erase() = 0;
virtual void GetBounds(std::pair<Point> & bounds) const = 0;
};
const unsigned IType_ISegmentedShape = 2;
class ISegmentedShape : public IShape
{
public:
virtual bool isa(unsigned type) const { return type == IType_ISegmentedShape || IShape::isa(type); }
virtual void AddSegment(const Point & a, const Point & b) = 0;
virtual unsigned GetSegmentCount() const = 0;
};
class Line : public IShape
{
public:
Line(std::pair<Point> extent) : extent(extent) { }
virtual void Draw();
virtual void Erase();
virtual void GetBounds(std::pair<Point> & bounds);
private:
std::pair<Point> extent;
};
class Polygon : public ISegmentedShape
{
public:
virtual void Draw();
virtual void Erase();
virtual void GetBounds(std::pair<Point> & bounds);
virtual void AddSegment(const Point & a, const Point & b);
virtual unsigned GetSegmentCount() const { return vertices.size(); }
private:
std::vector<Point> vertices;
};
Another option would be to make a single richer base interface class - which has all the interfaces you need, and then to simply define a default, no-op implementation for those in the base class, which returns false or throws to indicate that it isn't supported by the subclass in question (else the subclass would have provided a functional implementation for this member function).
class Shape
{
public:
struct Unsupported
{
Unsupported(const std::string & operation) : bad_op(operation) {}
const std::string & AsString() const { return bad_op; }
std::string bad_op;
};
virtual ~Shape() {} // ensure all subclasses are destroyed polymorphically!
virtual void Draw() = 0;
virtual void Erase() = 0;
virtual void GetBounds(std::pair<Point> & bounds) const = 0;
virtual void AddSegment(const Point & a, const Point & b) { throw Unsupported("AddSegment"); }
virtual unsigned GetSegmentCount() const { throw Unsupported("GetSegmentCount"); }
};
I hope that this helps you to see some possibilities.
Smalltalk had the wonderful attribute of being able to ask the meta-type-system whether a given instance supported a particular method - and it supported having a class-handler that could execute anytime a given instance was told to perform an operation it didn't support - along with what operation that was, so you could forward it as a proxy, or you could throw a different error, or simply quietly ignore that operation as a no-op).
Objective-C supports all of those same modalities as Smalltalk! Very, very cool things can be accomplished by having access to the type-system at runtime. I assume that .NET can pull of some crazy cool stuff along those lines (though I doubt that its nearly as elegant as Smalltalk or Objective-C, from what I've seen).
Anyway, ... good luck :)