How does constructor conversion work in C++? - c++

How does constructor conversion work?
#include <iostream>
using namespace::std;
class One {
public:
One() { cout<<"One"<<endl;}
};
class Two {
public:
Two(const One&) {cout<<"Two(const One&)"<<endl;}
};
void f(Two) {cout<<"f(Two)"<<endl;}
int main() {
One one;
f(one);
}
produces the output
One
Two(const One&)
f(Two)

Any constructor that can be called with a single argument is considered an implicit conversion constructor. This includes simple 1-argument cases, and usage of default arguments.
This conversion is considered in any context that wants X and provided Y, and Y has such implicit conversion possibility. Note that a plenty of other, built-in conversions also play as a mix (like adjusting const-ness, integral and fp promotions, conversions, etc.) The rule is that at most one "user defined" implicit conversion is allowed in the mix.
In some cases it may be quite surprising, so the general advice is to make any such ctors explicit. That keyword makes the conversion possible but not implicitly: you must use T() syntax to force it.
As an example consider std::vector that has a ctor taking size_t, setting the initial size. It is explicit -- otherwise your foo(vector<double> const& ) function could be mistakenly called with foo(42).

It's right result. Since constructor is not explicit - implicit conversion works (here One is implicitly converted to Two).
one is created, then when passed to f converted to Two.

What the Two(const One&) {cout<<"Two(const One&)"<<endl;} constructor means is that you're allowed to construct a Two value at any time - implicitly - from a One. When you call f(one) it wants a Two parameter, it's given a One, so the compiler puts 2 and 2 together and says "I'll make a temporary Two from the One and complete the call to f()"... everyone will be happy. Hurray!

Compiler has to create copy of Two instance on stack. When you call f() with argument which is object of class One (or any other) compiler looks to definition of class Two and tries to find constructor which takes One(or any other) object(or reference) as an argument. When such constructor has been found it constructs object using it. It's called implicit because compiler do it without your interference.
class Foo {
public:
Foo(int number) {cout<<"Foo(int number)"<<endl;}
};
void f(Foo) {cout<<"f(Foo)"<<endl;}
int main() {
f(24);
} ///:~
Output will be:
Foo(int number)
f(Foo)

Related

C++ literal passed to const reference leads to automatic construction

If I call the "func(const generic& ref)" with an integer as argument (instead of a 'generic' object), the constructor generic(int _a) will be called to create a new object.
class generic {
public:
int a;
generic() {}
generic(int _a) : a(_a) {
std::cout << "int constructor was called!";
}
generic(const generic& in) : a(in.a) {
std::cout << "copy constructor was called!";
}
};
void func(const generic& ref) {
std::cout << ref.a;
}
int main() {
generic g(2);
func(g); // this is good.
func(generic(4)); // this is good.
func(8); // this is good...... ?
return 0;
}
The last "func(8)" call creates a new object using the constructor generic(int _a). Is there a name for this kind of construction? Shouldn't the programmer explicitly construct an object before passing the argument? Like this:
func(generic(8));
Is there any benefit in passing the integer alone (other than saving time)?
This behavior is part of overload resolution process - specifically.
When you call func(), the compiler constructs a list of candidates. There's only one candidate, func(const generic& ref), so the compiler tries to figure out how to make a call.
It sees that there is no func(int) defined, so it tries to find a conversion path from int to generic. Since there is a constructor of generic that takes an int, and there are no other conversions allowing to perform the same call, the compiler takes the construction+call path.
The compiler checks three things, in the order from higher to lower priority:
Exact match
Promotion
Conversion
This means that an exact match of the signature trumps a match that requires a promotion, and a match that requires a promotion trumps a match that needs a conversion.
See "Ranking of implicit conversion sequences" of the document linked above for information on how implicit conversions are applied.
Is there a name for this kind of construction? Shouldn't the programmer explicitly construct an object before passing the argument?
If you don't want this to happen, you can add the explicit specifier to your constructor:
explicit generic(int _a) : a(_a)
{
std::cout << "int constructor was called!";
}
An excerpt from the cppreference page:
A constructor that is declared without the function specifier explicit is called a converting constructor.
By default, implicit constructor calls are allowed in this circumstance.
Is there any benefit in passing the integer alone (other than saving time)?
Whether you call the method with func(8) or func(generic(8)) isn't going to change what code executes given the code you have written. If you were to add an overload of func that takes an int instead of a generic, then the calls would suddenly become different. So, although it is ultimately a matter of opinion, I think you are better off being explicit by using func(generic(8)).

What causes this constructor to delegate to itself when it takes an initializer list and delegates a vector?

#include <initializer_list>
#include <vector>
struct test
{
using t = std::vector<test>;
test(t const &v)
{
}
test(t &&v)
{
}
test(std::initializer_list<test> v)
: test{t{v}} //error
{
}
};
Both Clang and GCC complain that the third constructor, the one taking the initializer list, delegates to itself. I don't understand how this is possible though, because you can't construct an initializer list from a vector.
It is trivial to fix the error by replacing the outer curly braces with round parenthesis, but why would this be an issue in the first place? This almost identical program compiles just fine:
#include <initializer_list>
struct a {};
struct b {};
struct test
{
test(a const &)
{
}
test(a &&)
{
}
test(std::initializer_list<b> v)
: test{a{}} //no error, still using curly braces
{
}
};
Interestingly, with the above second example, the error reappears if you substitute b with test. Can someone explain what is going on here?
The type of t{v} is std::vector<test>. The idea is that init-list constructors are always preferred wrt any other constructors, so test{t{v}} will first try to call an init-list constructor, if one exists, and if the types are compatible. In your case, this is possible, since test itself can be implicitly constructed from a std::vector<test> (via your first 2 constructors), so the compiler ends up delegating to the init-list constructor, hence the error.
In the second case, there is no ambiguity, since the type a{}is not implicitly convertible anymore to std::initializer_list<b>.
Make the constructors explicit in the first example, or call the base constructor with test(t{v}) instead, and your ambiguity will disappear (the compiler won't perform the implicit conversion anymore).
A simpler example (live here) that exhibits essentially the same behaviour as your first example is:
#include <initializer_list>
struct test
{
/*explicit*/ test(int){} // uncomment explicit and no more errors
test( std::initializer_list<test> v)
: test{42} {} // error, implicitly converts 42 to test(42) via the test(int)
};
int main(){}
The relevant part of the standard that deals with init-list constructors is §13.3.1.7/1 [over.match.list] - citation below taken from a now-deleted answer of #Praetorian -
When objects of non-aggregate class type T are list-initialized such that 8.5.4 specifies that overload resolution is performed according to the rules in this section, overload resolution selects the constructor in two phases:
— Initially, the candidate functions are the initializer-list constructors (8.5.4) of the class T and the argument list consists of the initializer list as a single argument.
— If no viable initializer-list constructor is found, overload resolution is performed again, where the candidate functions are all the constructors of the class T and the argument list consists of the elements
of the initializer list.
I'm no C++ expert but the main difference is that
test{a{}}
Does not have an overload for initializer_list<a> so that constructor is not available.
On the other hand test{t{v}} does have an initializer_list<test> constructor available to it because you can create a test from vector. It can use the (I don't know the name of the rule) 1 cast transformation.
test{t{v}} -> test{test(t{v})}
The problem in your code is that you're writing a function calling itself.
test(std::initializer_list<test> v)
: test{t{v}} //error
{
}
test{t{v}} will first call the initializer-list of vector<test> with v as parameter. But vector will call the function again to initialize the value which will fail.
The compiler doesn't know how to resolve the problem. Changing the initialization to use parentheses will (as you said) fix this because it will then call an implicit copy constructor in the vector (doing nothing because the your structure isn't doing anything).
The second example starts with this call: a{}
It is resolved fine because a is a basic structure with implicitly defined constructors. The second call is the test{...} one
Because the type is a and there is a constructor for a it runs just fine.

return type of std::bind implicitly convertible to two different explicit constructors

Given two explicit constructor overloads (based on different std::function<...> types), the return value of std::bind is able to select either (thereby making the call ambiguous)
call of overloaded ‘Bar(std::_Bind_helper<false, void (Foo::*)(int),
Foo*, int>::type)’ is ambiguous
If I comment out either, then the code compiles!
I would have thought making the constructors explicit would have either selected the correct overload, or prevented both from being selected?
Of course explicitly creating a std::function at the point I bind works:
Bar b(std::function<void(int)>(std::bind((&Foo::process), &f, 1)));
However, I'm puzzled as to why type deduction doesn't work?
If the return value from std::bind matches neither of the two constructor signatures, the fact they are explicit should prevent both from being selected.
If the return value from std::bind matches one of the two constructor signatures, the fact they are explicit should cause the correct one to be selected.
What is actually happening here?
Full working code below:
#include <functional>
struct Foo
{
void process(int) { }
};
struct Bar
{
// comment out either of these to compile
explicit Bar(std::function<void(int)>) {}
explicit Bar(std::function<void(short)>) {}
};
int main()
{
Foo f;
Bar b(std::bind(&Foo::process, &f, 1));
return 0;
}
Making the constructor explicit has nothing to do with the arguments having to match exactly! The affect of making a constructor explicit means that it won't be used to implicitly convert an object of a different type the type Bar using this constructor. However, if you try to initialize a Bar object using direct initialization (i.e., Bar(x)), both constructors will be considered.
The result of std::bind() is certainly not a std::function<Signature>, i.e., it doesn't match either of your constructors exactly. Since there is a non-explicit constructor for std::function<Signature> which works for function objects, both signatures do match: the produced bind expression doesn't require any parameter but it can take arguments, i.e., any argument type also cannot be used to distinguish which of the two constructors of Bar should match. Even if the bind expression would require one argument, I don't think it would be used to prefer one constructor over another.

Overloaded constructor - constructur with bool argument has precedence

I recently came across a class like the following
class Foo {
public:
Foo(std::string msg) {}
private:
Foo(bool b) {}
};
I noticed that trying to create an object of this class by means of
Foo foo("blah");
causes a compilation error telling that Foo::Foo(bool) is private. Apparently, if the argument is not an actual std::string, the compiler prefers to use the constructor with the bool argument. On the other hand, if the private constructor is not given, above code compiles just fine.
Why is it that the "bool-constructor" has precedence over the "string-constructor" althogh the type of the passed argument does not fit to any of them? Is this just a matter of definition or does it have a deeper meaning and some good reason?
The reason has to do with conversion operator precedence. Each of the calls includes an implicit conversion
pointer -> std::string
pointer -> bool
In this case #1 is a user defined conversion and #2 is a language / compiler defined one. User defined conversions have a much lower precedence and hence the other conversion is preferred.
Edit
Here is a similar question which has a much more in depth explanation of the precedence checks involved
conversion precedence in c++

C++ operator overloading synthetic conversion

This example is from "Thinking in C++", I have one question regarding compiler synthesizing the operator conversion function.
Question
When object of class Four is passed (in the function call f()), the overload operation () is called. But I am not able to make out the logic used (compiler synthesizes the operation call) by compiler to achieve this conversion.
At max, I can expect explicit conversion behavior, like
1. obj3 = (Three)obj4;
2. obj3 = Three(obj4);
3. obj3 = static_cast<Three> (obj4);
Now for any one of the above conversion - how does the compiler synthesize,
(Three) obj4.operator()?
May be I am missing some major point.
Example
//: C12:Opconv.cpp
// Op overloading conversion
class Three {
int i;
public:
Three(int ii = 0, int = 0) : i(ii) {}
};
class Four {
int x;
public:
Four(int xx) : x(xx) {}
operator Three() const { return Three(x); }
};
void g(Three) {}
int main() {
Four four(1);
g(four);
g(1); // Calls Three(1,0)
} ///:~
First of all it is not operator() which you have provided, it is operator Three. This operator tells the compiler how to convert an object of class Four to an object of class Three. In g(four) call compiler is using this operator since the function g is expecting an argument of type Three. Since there is an conversion available compiler is using it. In the second case, since the constructor of Three is not declared as explicit and it is possible to construct a object of class Three using a single integer (using Three constructor) compiler is using that constuctor to create an object of the class Three so that function g can be called.
First of all, class Four does not contain an operator(), but it does have an operator Three(), which is a conversion operator.
In the line
g(four);
the compiler needs to convert four to an object of class Three and synthesises a call to operator Three() to perform that conversion.
The synthesised conversion is equivalent to
g(four.operator Three());