Reputation: 33
Apologies if I am not using C++ nomenclature correctly. I also tried searching StackOverflow and Cppreference but couldn't find information about this case.
Let's take the following piece of code.
struct Foo{
vector<int> vec;
Foo(vector<int> inp) : vec(inp){};
};
struct Bar {
Foo foo;
Bar(Foo inp) : foo(inp) {};
};
int main()
{
vector<int> vec = {1,2,3};
Foo foo(vec);
Bar bar1(foo);
Bar bar2(vec);
}
So, I have Bar
which has a member Foo
. Foo
is supposed to be initialised with a vector, while Bar
takes Foo
as a constructor argument. Nothing unusual here.
Surprisingly, I noticed that I am allowed to do Bar bar2(vec)
. Looks like there exists an implicitly defined constructor which could look like Bar(vector<int> vec) : foo(vec){}
.
This is quite surprising to me. From what I know, c++ only implicitly generates default, move and copy constructs, as well as destructors. In this case, it looks like it generates a constructor which mirrors the member's argument list and passes it to the member's constructor. Is it what happens in reality? Could you please provide some more information about this behaviour?
Upvotes: 1
Views: 147
Reputation: 172884
Foo
has a converting constructor taking a vector
. In Bar bar2(vec);
, vec
is implicitly converted to a temporary Foo
via the converting constructor, then the temporary Foo
is passed to the constructor of Bar
as an argument.
You can mark the Foo
constructor as explicit
to prohibit the implicit conversion:
struct Foo{
vector<int> vec;
explicit Foo(vector<int> inp) : vec(inp){};
};
BTW: Bar::Bar(Foo)
is a converting constructor, too.
Upvotes: 4