Factory can't access friend's constructor

I have a factory:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class FordFactory : public ICarFactory
{
public:
	FordFactory() { }
	~FordFactory() { }

	std::unique_ptr<Car> assemble() override
	{
		return std::make_unique<Ford>();
	}

private:

};


and a resource that it produces

1
2
3
4
5
6
7
8
9
10
11
12
class FordFactory;
class Ford : public Car
{
public:
	friend class FordFactory;

protected:
	Ford();

private:

};


but I'm getting error:

error: calling a protected constructor of class 'Ford'

when trying to compile. I assumed the friendship of the FordFactory to the Ford made it so that FordFactory could access Ford's constructor directly, as I do not want a client to instantiate a Ford directly, but rather use the factory.

I'm probably missing something obvious.

Any ideas?
It's make_unique that seems to have trouble accessing the protected ctor. I don't know if this is a good fix, but it works if you don't use make_unique:

1
2
3
    std::unique_ptr<Car> assemble() override {
        return std::unique_ptr<Ford>(new Ford);
    }

post enought code to reproduce your issue
all includes needed, all classes definitions, and main() function

> error: calling a protected constructor of class 'Ford'
|| In file included from 'foo.cpp':
|| In file included from 'memory':
'unique_ptr.h' error: calling a protected constructor of class 'Ford'
note: in instantiation of function template specialization 'std::make_unique<Ford>' ...
make_unique is trying to call Ford constructor
make_unique is not a friend of Ford
(¿see why context is important?)


not sure how to fix it
making make_unique a friend of Ford will break the protected constructor (you may call make_unique from any function, not just the factory)
you may discard the make_unique and use new
or you may use passkey idiom (which i just read about)
https://stackoverflow.com/a/29897660
https://arne-mertz.de/2016/10/passkey-idiom/
For this example, all of those peripheral files aren't really necessary, as this example is a pretty trivial representation of an abstract factory design pattern, and they'd only really confuse the situation.

With that said, it seems that you and @Dutch had the same conclusion: unique_ptr is trying to access a private constructor.

Personally, I just solved this by having the factory return raw pointers, and simply wrap the raw pointers in std::unique_ptr once it's returned.

Thanks!
For this example, all of those peripheral files aren't really necessary, as this example is a pretty trivial representation of an abstract factory design pattern, and they'd only really confuse the situation.

No-one's asking ypou to post all of your code. People are asking you to post a minimal, compilable codeset that demonstrates the problem. That's enormously helpful when investigating problems - for you, as well as for anyone else who's trying to help you.
No-one's asking ypou to post all of your code. People are asking you to post a minimal, compilable codeset that demonstrates the problem.


My point is that I knew the problem was specifically in those two code snippets at the time of posting, and that a static analysis of that code would be enough to solve the issue -- and lo behold -- it was. As in, I suspected it was an issue with unique_ptr trying to access a private constructor, but just wanted someone else's unbiased opinion.

I've also found that shorter, more concise problem statements yield a response more often.

Which is to say, what I posted was a good compromise between an inconvenience to me and an inconvenience to the reader. I didn't have to take an enormous amount of time making a large post on this site (which is painful when the code block buttons don't work on Windows) and the reader didn't have to copy my large post into an IDE to compile it just to find out that there was a simple solution.
Last edited on
> that a static analysis of that code would be enough to solve the issue -- and lo behold -- it was
it wasn't
I had to create Car and ICarFactory classes, move the code around, include some headers to obtain a sane error message (the one I posted)
and also need all that to test the solutions

I doesn't matter that those classes end up being empty, ¿why should I have to code them?
you have a compile error, I want to get a compile error, don't withhold information

> it seems that you and @Dutch had the same conclusion: unique_ptr is trying to
> access a private constructor.
no, read again
make_unique is trying to access a private constructor

> I just solved this by having the factory return raw pointers, and simply wrap
> the raw pointers in std::unique_ptr once it's returned.
¿do you mean like Car* assemble();?
¿why don't use dutch's solution?
Last edited on
Look, here's the deal: If you don't want to exert the effort to solve a problem, don't solve it. Not all problems are going to be phrased exactly as you'd like them to be.

When posing the original question I realized there were going to be people who looked at the question and went "Gee, there's not enough information here to solve the issue". Those were not the people I wanted answering the question; they were not my "target audience", as it were.

I particularly posed the question in such a way that people who were familiar with factories and have run into this problem before had a quick solution. As in, someone saying:

"Oh yeah, that's a common mistake of people who are first learning the factory design pattern. I did it too. Here's what I did to solve the issue."

I'm not responsible for the effort you exerted to solve the problem. That's entirely your prerogative, just as its my prerogative to pose a question any way I see fit and accept the consequences of it being answered or not based on how I posed it. Personally, I've found the way I post questions gets me the responses I want. If that changes, I'll change how I post my questions.

I'm not sure why people are being so pedantic about this when literally the FIRST answer to my question was EXACTLY what I was looking for.
> It's make_unique that seems to have trouble accessing the protected ctor.
> I don't know if this is a good fix, but it works if you don't use make_unique:
> return std::unique_ptr<Ford>(new Ford);

It is a good fix.
(Trying to) make std::make_unique<> a friend is not a good idea, for more than one reason
Topic archived. No new replies allowed.