This code below is based on the CPP Core Guidelines, Appendix C, "Discussion: Use a factory function if you need "virtual behavior" during initialization"
The idea in the code is to use a factory function to instantiate derived classes that require a 'post constructor' to be called in in the derived class.
The code I have is this:
#include <iostream>
#include <memory>
using namespace std;
class B {
protected:
class Token {};
public:
// constructor needs to be public so that make_shared can access it.
// protected access level is gained by requiring a Token.
explicit B(Token) { /* ... */ } // create an imperfectly initialized object
template<class T>
static shared_ptr<T> create() // interface for creating shared objects
{
auto p = make_shared<T>(typename T::Token{});
p->post_initialize();
return p;
}
private: //change to protected and it compiles in C Builder
void post_initialize() // called right after construction
{ /* ... */ f(); /* ... */ } // GOOD: virtual dispatch is safe
virtual void f() = 0;
};
class D : public B { // some derived class
protected:
class Token {};
public:
// constructor needs to be public so that make_shared can access it.
// protected access level is gained by requiring a Token.
explicit D(Token) : B{ B::Token{} } {}
D() = delete;
protected:
//Make B:create() a friend so it can access private and protected members...
template<class T>
friend shared_ptr<T> B::create();
private:
void f() override {
std::cout << "I'm a D" << std::endl;
};
};
int main() {
shared_ptr<B> p = B::create<D>(); // creating a D object
return 0;
}
This code compiles and runs using MinGW version w64 9.0 and MSVC 2022. However C Builder 11.5 Alexandria, Clang compiler, 32 bit and 64 bit, complains that: "error: 'post_initialize' is a private member of 'B'"
But if I change Class B's private: section to protected: C Builder compiles the code.
I expected C Builder to compile this as B::create() should be able to call a private function of B should it not?
Or am I wrong and MinGW and MSVC are incorrectly able to compile this?
Andy
CodePudding user response:
I expected C Builder to compile this as B::create() should be able to call a private function of B should it not?
Yes, post_initialize
is allowed to be used/called like p->post_initialize()
from inside B::create()
as both belong to the same class.
This looks like a C Builder bug as per your error description.