Reputation: 14484
A default member initialisation needs to reference an existing constructor, no matter if it is ever used or not. So, looking at a struct Foo
which has no default constructor:
struct Foo{
Foo(int x) : x_(x){}
int x_;
};
It is clear that the following wouldn't work, and leads to a compilation error:
class Bar0{
Foo foo = Foo(); #constructor Foo() doesn't exist
Bar0() : foo(0){}
}
But, it is a different story with std::unique_ptr
and std::make_unique
:
class Bar1{
unique_ptr<Foo> foo = make_unique<Foo>(); #compiler doesn't complain
Bar1() : foo(make_unique<Foo>(0)){}
}
This is puzzling, as the compilation fails as soon as Bar1
contains one constructor where foo
is not in the initialiser list.
I can confirm this to be true of MSVC12. Could it be a compiler bug?
Upvotes: 1
Views: 3759
Reputation:
Here is a self-contained sample demonstrating the problem:
template <typename T>
int f() {
return T();
}
struct S {
int i = f<void>();
S() : i(0) { }
};
In your example, f
is named make_unique
, and it doesn't return int
, but that doesn't fundamentally change anything.
Yes, Visual Studio's compiler accepts that, and other compilers don't. Visual Studio delays instantiating the templates it doesn't yet need. Other compilers instantiate f<void>
as soon as they spot the reference.
Quoting from C++11:
14.7.1 Implicit instantiation [temp.inst]
9 If a function template or a member function template specialization is used in a way that involves overload resolution, a declaration of the specialization is implicitly instantiated (14.8.3).
This supports the compilers that issue an error: f<void>()
requires overload resolution, so this instantiates f<void>
. There's some leeway for class template instantiations:
14.7.1 Implicit instantiation [temp.inst]
6 If the overload resolution process can determine the correct function to call without instantiating a class template definition, it is unspecified whether that instantiation actually takes place.
but (contrary to what I initially wrote in my answer) I don't think it applies to whole function bodies.
Unless there is a similar exception for function templates, and I haven't been able to find one, I think compilers are required to diagnose the error, and lazy instantiation is not actually currently allowed for function templates.
Upvotes: 5