尝试在具有私有(private) ctor 的类上允许 make_unique
我遇到了以下两种情况之间的奇怪差异:
案例 1 - 空 ctor - 编译
class A {
int _i;
A(): _i(7) {}
public:
template<typename... T>
static std::unique_ptr<A> create(T&&... t) {
struct enablePrivateCtor : public A {
using A::A;
};
return std::make_unique<enablePrivateCtor>(std::forward<T>(t)...);
}
void doIt() const {
std::cout << _i << std::endl;
}
};
int main() {
auto a = A::create();
a->doIt();
}
输出:
7
情况 2 - 非空构造函数 - 不编译
class A {
int _i;
A(int i): _i(i) {} // <- change 1, ctor getting int
public:
// no change here!
template<typename... T>
static std::unique_ptr<A> create(T&&... t) {
struct enablePrivateCtor : public A {
using A::A;
};
return std::make_unique<enablePrivateCtor>(std::forward<T>(t)...);
}
void doIt() const {
std::cout << _i << std::endl;
}
};
int main() {
auto a = A::create(7); // <- change 2, sending 7
a->doIt();
}
编译错误:
unique_ptr.h: error: calling a private constructor of class 'enablePrivateCtor'
为什么第一个 - 带有空 ctor - 可以,而第二个 - 非空 ctor - 不行?
最佳答案
默认构造函数永远不会被继承。因此,第一个enablePrivateCtor
生成一个默认构造函数,调用基类默认构造函数。
当您继承构造函数时(如第二种情况),新构造函数与继承的构造函数具有相同的访问级别。因此,由于 A::A(int)
是私有(private)的,因此 enablePrivateCtor::enablePrivateCtor(int)
也是私有(private)的。因此,您将无法使用它进行构建。
如果您需要让私有(private)构造函数能够被间接调用(通过make_unique
/emplace
/等),那么您需要使用私钥类型。像这样:
class A;
class A_key
{
A_key() = default;
A_key(int) {} //Prevent `A_key` from being an aggregate.
friend class A;
};
class A {
int _i;
public:
A(int i, A_key): _i(i) {}
// no change here!
template<typename... T>
static std::unique_ptr<A> create(T&&... t)
{
return std::make_unique<A>(std::forward<T>(t)..., A_key{});
}
void doIt() const {
std::cout << _i << std::endl;
}
};
...
auto ptr = A::create(7);
A a(7, A_key{}); //Does not compile, since you're not a friend.
A_key
可公开复制,但不可公开默认构造。所以非私有(private)代码可以传递它们,但非私有(private)代码不能创建它们。
关于c++ - 继承私有(private)构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46157775/