构造函数中的C ++自动类型推导

时间:2017-11-27 17:40:47

标签: c++ c++14

我想了解我今天看到的以下代码。我已经尝试找到一个相关的问题,但由于我不知道C ++的这个特性是什么,所以很难找到相关的帖子。对正确搜索词的提示可能对我有帮助。

struct A
{ int x; };

struct B
{ B(A a) {}; };

int main()
{
    B b{ { 5 } }; // works, seems to create a struct A from {5} and pass it to B's constructor
    std::make_unique<B>({ 5 }); // doesn't compile
    return 0;
}

为什么{5}在传递给make_unique时不用于创建结构A,而是在B的构造函数中以这种方式使用?

如果B有第二个构造函数B(int foo) {};,那么将使用这个构造函数而不是上面的一个构造函数(至少这是我通过反复试验找到的)。决定参数是自动用于创建struct A还是在构造函数中直接用作int的规则是什么?

我正在使用Visual C ++ 14.0

2 个答案:

答案 0 :(得分:5)

这是一个简化的演示:

struct X { X(int); };

void foo(X );
template <typename T> void bar(T );

foo({0}); // ok
bar({0}); // error

问题是 braced-init-list ,那些只是浮动{...}的构造,是C ++中的奇怪怪物。他们没有类型 - 他们的意思必须从他们实际使用的方式推断出来。当我们调用foo({0})时, braced-init-list 用于构造X,因为这是参数 - 它的行为就像我们编写X{0}一样。

但是在bar({0})中,我们没有足够的背景知道如何处理它。我们需要从参数中推导出T,但是参数没有类型 - 所以我们可以推导出哪种类型?

在这种情况下,使其有效的方法是明确提供T

bar<X>({0}); // ok

或提供具有可推断类型的参数:

bar(X{0});   // ok

在原始示例中,您可以直接提供A

make_unique<B>(A{5})
直接

B

make_unique<B>(B({5}))

或只使用new

unique_ptr<B>(new B({5}))

或者,不太偏爱且有些疑问,明确指定模板参数:

make_unique<B, A>({5});

答案 1 :(得分:-2)

在没有函数说明符explicit的情况下声明的具有单个非默认参数(直到C ++ 11)的构造函数称为转换构造函数。您的AB是此类构造函数的实例(这解释了为什么您的第一个调用正常。)问题是,std::make_unique阻止了这些显式调用。无论如何,这可能是一个好主意,首先不要相信这些自动创建,并花费一些字符来显示类型。这可以提高代码的可读性。