I apologize for the large amount of code needed to demonstrate the problem. I have a problem using the pimpl idiom with std :: unique_ptr. In particular, a problem occurs when one class (which has a pimpl'ed implementation) is used as element data in another composite class with a pimpl'ed implementation.
Most of the answers that I could find with no explicit declaration of the destructor , but as you can see here, I declared and defined the destructors.
What is wrong with this code, and is it possible to modify it for compilation without changing the design?
Note: an error occurs in the definition of SomeComposite :: getValue () and that the compiler cannot see the error until compilation. An error occurs in .h memory, and the message is an invalid application 'sizeof' to the incomplete type 'pimplproblem :: SomeInt :: impl'.
SomeInt.h
#pragma once
#include <iostream>
#include <memory>
namespace pimplproblem
{
class SomeInt
{
public:
explicit SomeInt( int value );
SomeInt( const SomeInt& other );
SomeInt( SomeInt&& other ) = default;
virtual ~SomeInt();
SomeInt& operator=( const SomeInt& other );
SomeInt& operator=( SomeInt&& other ) = default;
int getValue() const;
private:
class impl;
std::unique_ptr<impl> myImpl;
};
}
SomeInt.cpp
#include "SomeInt.h"
namespace pimplproblem
{
class SomeInt::impl
{
public:
impl( int value )
:myValue( value )
{}
int getValue() const
{
return myValue;
}
private:
int myValue;
};
SomeInt::SomeInt( int value )
:myImpl( new impl( value ) )
{}
SomeInt::SomeInt( const SomeInt& other )
:myImpl( new impl( other.getValue() ) )
{}
SomeInt::~SomeInt()
{}
SomeInt& SomeInt::operator=( const SomeInt& other )
{
myImpl = std::unique_ptr<impl>( new impl( other.getValue() ) );
return *this;
}
int SomeInt::getValue() const
{
return myImpl->getValue();
}
}
SomeComposite.h
#pragma once
#include <iostream>
#include <memory>
#include "SomeInt.h"
namespace pimplproblem
{
class SomeComposite
{
public:
explicit SomeComposite( const SomeInt& value );
SomeComposite( const SomeComposite& other );
SomeComposite( SomeComposite&& other ) = default;
virtual ~SomeComposite();
SomeComposite& operator=( const SomeComposite& other );
SomeComposite& operator=( SomeComposite&& other ) = default;
SomeInt getValue() const;
private:
class impl;
std::unique_ptr<impl> myImpl;
};
}
SomeComposite.cpp
#include "SomeComposite.h"
namespace pimplproblem
{
class SomeComposite::impl
{
public:
impl( const SomeInt& value )
:myValue( value )
{}
SomeInt getValue() const
{
return myValue;
}
private:
SomeInt myValue;
};
SomeComposite::SomeComposite( const SomeInt& value )
:myImpl( new impl( value ) )
{}
SomeComposite::SomeComposite( const SomeComposite& other )
:myImpl( new impl( other.getValue() ) )
{}
SomeComposite::~SomeComposite()
{}
SomeComposite& SomeComposite::operator=( const SomeComposite& other )
{
myImpl = std::unique_ptr<impl>( new impl( other.getValue() ) );
return *this;
}
SomeInt SomeComposite::getValue() const
{
return myImpl->getValue();
}
}
source
share