Consider the following example:
#include <iostream>
#include <memory>
struct A
{
explicit A(int x)
{
std::cout << x << std::endl;
}
};
void Foo(A ) {}
std::shared_ptr<A> Foo2(int x)
{
// why does this work?
return std::make_shared<A>(x);
}
int main()
{
A a(0);
Foo(a);
// Foo(1); does not compile
Foo2(2);
}
I have a class A
with an explicit marked constructor so that it doesn't convert from int
to the class A
implicitly. But in a call to std::make_shared
I can call and create this class by only passing an int
. Why is that possible and is there something wrong in the way how I do it?
CodePudding user response:
This is expected behavior, because std::make_shared
performs direct-intialization, which considers explicit constructors too.
The object is constructed as if by the expression
::new (pv) T(std::forward<Args>(args)...)
Direct-initialization is more permissive than copy-initialization: copy-initialization only considers non-explicit constructors and non-explicit user-defined conversion functions, while direct-initialization considers all constructors and all user-defined conversion functions.
Foo(1);
doesn't work because the parameter gets copy-initialized, which won't consider explicit constructors.