无论成员是否使用过,默认成员初始化都需要引用现有的构造函数。因此,看一个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
包含一个foo
不在初始化列表中的构造函数,编译就会失败。
我可以确认这对MSVC12是正确的。可能是编译器错误吗?
这是一个独立的示例,演示了该问题:
template <typename T>
int f() {
return T();
}
struct S {
int i = f<void>();
S() : i(0) { }
};
在您的示例中,f
名为make_unique
,它不会返回int
,但是从根本上不会改变任何内容。
是的,Visual Studio的编译器接受,其他编译器则不接受。Visual Studio延迟实例化它不需要的模板。其他编译器f<void>
在发现引用后立即实例化。
从C ++ 11引用:
14.7.1隐式实例化[temp.inst]
9如果以涉及过载解析的方式使用函数模板或成员函数模板特化,则隐式实例化特化的声明(14.8.3)。
这支持发出错误的编译器:f<void>()
需要重载解析,因此将实例化f<void>
。类模板实例化还有一些余地:
14.7.1隐式实例化[temp.inst]
6如果重载解析过程可以在不实例化类模板定义的情况下确定要调用的正确函数,则不确定该实例是否实际发生。
但是(与我最初在回答中写的相反),我认为它不适用于整个函数体。
除非功能模板存在类似的例外,并且我无法找到一个例外,否则我认为需要编译器来诊断错误,并且功能模板目前实际上不支持惰性实例化。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句