C++ 为什么std::make_unique在从未调用的默认成员初始化中不需要参数?

C++ 为什么std::make_unique在从未调用的默认成员初始化中不需要参数?,c++,c++11,initialization,default,unique-ptr,C++,C++11,Initialization,Default,Unique Ptr,默认成员初始化需要引用现有构造函数,无论是否使用过它。因此,看看没有默认构造函数的structFoo: struct Foo{ Foo(int x) : x_(x){} int x_; }; 很明显,以下操作不起作用,并导致编译错误: class Bar0{ Foo foo = Foo(); #constructor Foo() doesn't exist Bar0() : foo(0){} } 但是,对于std::unique_ptr和std::make_u

默认成员初始化需要引用现有构造函数,无论是否使用过它。因此,看看没有默认构造函数的struct
Foo

struct Foo{
    Foo(int x) : x_(x){}
    int x_;
};
很明显,以下操作不起作用,并导致编译错误:

class Bar0{
    Foo foo = Foo(); #constructor Foo() doesn't exist
    Bar0() : foo(0){}
}
但是,对于
std::unique_ptr
std::make_unique
,情况就不同了:

class Bar1{
    unique_ptr<Foo> foo = make_unique<Foo>(); #compiler doesn't complain
    Bar1() : foo(make_unique<Foo>(0)){}
}
类Bar1{
unique_ptr foo=make_unique();#编译器不会抱怨
Bar1():foo(使_唯一(0)){}
}
这令人费解,因为只要
Bar1
包含一个构造函数,而
foo
不在初始化器列表中,编译就会失败


我可以证实MSVC12的这一点。这可能是编译器错误吗?

下面是一个自包含的示例,演示了该问题:

template <typename T>
int f() {
  return T();
}

struct S {
  int i = f<void>();
  S() : i(0) { }
};
模板
int f(){
返回T();
}
结构{
int i=f();
S():i(0){}
};
在您的示例中,
f
被命名为
make_unique
,它不会返回
int
,但这不会从根本上改变任何东西

是的,VisualStudio的编译器接受这一点,而其他编译器则不接受。VisualStudio延迟实例化它还不需要的模板。其他编译器一发现引用就实例化
f

引用C++11:

14.7.1隐式实例化[temp.inst]

9如果以涉及重载解析的方式使用函数模板或成员函数模板专用化,则会隐式实例化专用化声明(14.8.3)

这支持发出错误的编译器:
f()
需要重载解析,因此这将实例化
f
。类模板实例化有一定的回旋余地:

14.7.1隐式实例化[temp.inst]

6如果重载解析过程可以在不实例化类模板定义的情况下确定要调用的正确函数,则未指定该实例化是否实际发生

但是(与我最初在回答中写的相反),我认为它不适用于整个函数体


除非函数模板也有类似的异常,而且我还没有找到,否则我认为需要编译器来诊断错误,并且函数模板目前实际上不允许延迟实例化。

下面是一个自包含的示例,演示了该问题:

template <typename T>
int f() {
  return T();
}

struct S {
  int i = f<void>();
  S() : i(0) { }
};
模板
int f(){
返回T();
}
结构{
int i=f();
S():i(0){}
};
在您的示例中,
f
被命名为
make_unique
,它不会返回
int
,但这不会从根本上改变任何东西

是的,VisualStudio的编译器接受这一点,而其他编译器则不接受。VisualStudio延迟实例化它还不需要的模板。其他编译器一发现引用就实例化
f

引用C++11:

14.7.1隐式实例化[temp.inst]

9如果以涉及重载解析的方式使用函数模板或成员函数模板专用化,则会隐式实例化专用化声明(14.8.3)

这支持发出错误的编译器:
f()
需要重载解析,因此这将实例化
f
。类模板实例化有一定的回旋余地:

14.7.1隐式实例化[temp.inst]

6如果重载解析过程可以在不实例化类模板定义的情况下确定要调用的正确函数,则未指定该实例化是否实际发生

但是(与我最初在回答中写的相反),我认为它不适用于整个函数体


除非函数模板也有类似的例外情况,而且我还没有找到,否则我认为需要编译器来诊断错误,而函数模板目前实际上不允许延迟实例化。

相关:以及您的“make_unqiue”打字错误,再加上对ISO/IEC 14882-2011的详尽搜索没有发现名为“make_unique”的标准库函数,这表明这不是您遇到问题的实际代码,而是您凭空提取的一些随机代码片段。如果您想问一个问题并参考一些代码,请发布您遇到问题的实际代码。谢谢。@SamVarshavchik
使您独一无二
和。我直接从VisualStudio项目中提取了这段代码,除了一个空的主函数之外,它是其中唯一包含的东西。排版一定是在编辑过程中滑进去的。如果你看到任何其他方法来改进这个问题,请告诉我。相关:和你的“make_unqiue”打字错误,再加上一个事实,即对ISO/IEC 14882-2011的彻底搜索没有发现一个名为“make_unique”的标准库函数,表明这不是你遇到问题的实际代码,但是一些你从稀薄的空气中提取的随机代码片段。如果您想问一个问题并参考一些代码,请发布您遇到问题的实际代码。谢谢。@SamVarshavchik
使您独一无二
和。我直接从VisualStudio项目中提取了这段代码,除了一个空的主函数之外,它是其中唯一包含的东西。排版一定是在编辑过程中滑进去的。如果你有其他方法来改进这个问题,请告诉我。啊,我明白了。模板函数
make_unique()
从未被实例化,因为MSVC确定它将永远不会被调用,因此对
Foo()
的无效调用甚至不存在。非常感谢。@Ifreichit重读一遍,我想我的回答完全错了。上面写着“类模板定义”,参考