std::make_shared<>(), has access to protected constructor

std::make_shared<>(), has access to protected constructor

Ritratto di tpucke

Hello, I'm using Intel's 12.1 compiler with Visual Studio 2010 IDE, making 64 bit target. See code in 2 attached files.

The problem is that this code compiles and it should trigger an error. As expected, it fails with the Microsoft compiler with error C2248 cannot access protected member... .

The Worker class constructor is not public and so it should not be accessible from std::make_shared<Worker>(...). Is this a compiler defect?

I have tried things such as making the Worker constructor private with the same outcome.
I tried completely removing the Worker constructor with 2 arguments, and the code still compiles with no complaint.
I tried making the call to std::make_shared in the constructor body rather than in member initialization. No improvement.
It seems like the compiler is not checking for access to construct the object managed by the std::shared_ptr<...>.

Thanks for looking

AllegatoDimensione
Scarica access.cpp417 byte
Scarica access.h558 byte
8 post / 0 new
Ultimo contenuto
Per informazioni complete sulle ottimizzazioni del compilatore, consultare l'Avviso sull'ottimizzazione
Ritratto di Sergey Kostrov

Thanks for the test case!

Ritratto di Georg Zitzlsberger (Intel)

Hello,

I can reproduce the problem you described. In my opinion this should not be the case -- any compiler has to error here. Hence I've filed a defect ticket (DPD200239413) and let you know about the status.

Thank you for the great reproducer!

Best regards,

Georg Zitzlsberger

Ritratto di Sergey Kostrov

Hi everybody,

>>...The Worker class constructor is not public and so it should not be accessible from std::make_shared(...). Is this a compiler defect?

Yes. Even if a member mpWorker is declared without the std::shared_ptr template class ( not as a smart pointer ):
...
Worker * operator ->() const;

protected:
// std::shared_ptr< Worker > mpWorker;
Worker *mpWorker;
};
...
any C++compiler should fail with some error, like:

...'Worker::Worker' : cannot access protected member declared in class 'Worker'...

Best regards,
Sergey

Ritratto di Sergey Kostrov

Here is a test-case that you could consider as a workaround ( passed with 5 different C/C++ compilers ):
...
class Worker
{
public:
Worker();
virtual ~Worker();

protected:
Worker( string const &vClientName, string const &vUserName );

public:
void SetNames( string const &vClientName, string const &vUserName )
{
mClientName = vClientName;
mUserName = vUserName;
};

protected:
string mClientName;
string mUserName;
};

class Handle
{
public:
Handle( string const &vClientName = "unknown", string const &vUserName = "unknown" );
Handle( Handle const &vRhs );
virtual ~Handle();

public:
Worker * operator ->() const;

protected:
// std::shared_ptr< Worker > mpWorker;
Worker mpWorker;
};

Worker::Worker()
{
}

Worker::Worker( string const &vClientName, string const &vUserName )
{
mClientName = vClientName;
mUserName = vUserName;
}

Worker::~Worker()
{
}

/*
Handle::Handle( string const &vClientName, string const &vUserName ) :
// mpWorker( std::make_shared< Worker >( vClientName, vUserName ) )
// mpWorker( Worker( vClientName, vUserName ) )
{
}
*/

Handle::Handle( string const &vClientName, string const &vUserName )
{
// Case 1 - Compiling error
// (*this).operator->()->mClientName = vClientName; // Cannot be used directly when the member is declared as protected in class 'Worker'
// (*this).operator->()->mUserName = vUserName;

// Case 2 - Compiling error
// mpWorker.mClientName = vClientName; // Cannot be used directly when the member is declared as protected in class 'Worker'
// mpWorker.mUserName = vUserName;

// Case 3 - Success
mpWorker.SetNames( vClientName, vUserName ); // Public 'SetNames(...)' method used instead to initialize members of class 'Worker'
}

Handle::~Handle()
{
}

Worker * Handle::operator ->() const
{
return ( Worker * )&mpWorker;
}

...
void main( void )
{
Handle objAccount( "MyClient", "MyUser" );
}

Ritratto di tpucke

Thanks for the suggestion. I have implemented a pass-key pattern that works around the access issue from std library, since I don't know the scope of the compiler issue.

Ritratto di Sergey Kostrov

>>... I don't know the scope of the compiler issue...

I personally would use a workaround ( Is that a big problem? No. ) because it will take some time to fix the problem with the compiler. At least you should be able to proceed with what you need to do etc.

Ritratto di Georg Zitzlsberger (Intel)

Hello,

this problem will be fixed in Intel(R) Composer XE 2013 Update 2 that's scheduled soon.

Best regards,

Georg Zitzlsberger

Accedere per lasciare un commento.