Why this discrepancy in the need for narrowing conversions? [duplicate] - c++

This question already has answers here:
Why is a narrowing conversion from int to float only needed if I brace-initialise an object?
(2 answers)
Why is const int fine for char brace init?
(1 answer)
Why doesn't braced initialization throw a narrowing error when converting from double to float?
(1 answer)
Why does a narrowing conversion warning appear only in case of list initialization?
(3 answers)
Closed 27 days ago.
I'm really confused about these rules:
void func(float f)
{
}
struct Foo
{
Foo(float b) {}
};
int main()
{
short b = 1;
func(b);/* WORKS FINE*/
Foo foo{ b }; /*REQUIRES NARROWING CONVERSION FROM SHORT TO FLOAT */
Foo foo2{ (short)b }; /* REQUIRES NARROWING CONVERSION FROM SHORT TO FLOAT */
Foo foo3{ (short)7 }; /* WORKS FINE */
}
My first question, why can I call func(float) with an l-value of a short, but not use it as an argument to the constructor?
My second question is, even if we look at the passing of a short to the constructor, then it doesn't complain when we hand it an r-value short. Why is this the case?

Related

Can anyone tell me what's wrong with the code below down? [duplicate]

This question already has an answer here:
Most vexing parse
(1 answer)
Closed 9 years ago.
Consider this code:
#include<iostream>
using namespace std;
class A
{
public:
A():age(12){}
int age;
};
int main()
{
A a();
cout << a.age << endl;
return 0;
}
When I compile it using g++, I get an error:
you can not see the member age, because a is not a class A()
Can someone explain this to me? What is A a()?
This line
A a();
declares a function named a, returning A with no arguments. (See Most vexing parse).
What you want is
A a = A(); // value-initialization
A a{}; // the same but only valid in C++11 (and currently not supported by MSVS)
or
A a; // default initialization
C++11, §8.5/10
Note: Since () is not permitted by the syntax for initializer,
X a();
is not the declaration of a value-initialized object of class X, but the declaration of a function taking no argument and returning an X.
For your class, value-initialization == default-initialization (at least for the outcome).
See my answer here: C++: initialization of int variables by an implicit constructor for Infos on value- vs. default-initialization for POD or built-in types.
It defines a function called a that returns an object of type A. This is known as the "most vexing parse".

Function Overloading with const [duplicate]

This question already has answers here:
Why is this call to member function ambiguous?
(3 answers)
Closed 5 years ago.
struct A
{
void fn(double a) const {}
void fn(int a){}
};
int main()
{
A().fn(1.);
}
For the above mentioned function why does the compiler produce an ambiguity; Both the types are different.
Why would you like to pass an int only to a non-const A?
There are two parameters to each member function, this and a. So you require a const A* for this and doublefor a, or non-const A* and int.
And the call doesn't fully match either alternative, as you have non-const Aand double. So the compiler can either convert A() to const A, or doubleto int. And it cannot decide which is the best.

'explicit' keyword in g++ has no effect for simple constructor (not copy/assignment constructor)? [duplicate]

This question already has answers here:
What does the explicit keyword mean?
(11 answers)
Closed 7 years ago.
Can anyone explain why the following code compiles? I expect it to get an error where the double constant 3.3 can not be converted to int, since I declare the constructor to be explicit.
class A
{
public:
int n;
explicit A(int _n);
};
A::A(int _n)
{
n = _n;
}
int main()
{
A a(3.3); // <== I expect this line to get an error.
return 0;
}
It works in the other way around. Let's define in addition to your code
void f(A a)
{
}
int main()
{
A a(3.3); // <== I expect this line to get an error.
f(5);
return 0;
}
Without the word explicit it would compile, with the explicit it would report an error. The keyword forbids casting from integer to A in situations like this.
explicit class_name ( params ) (1)
explicit operator type ( ) (since C++11) (2)
1) specifies that this constructor is only considered for direct initialization (including explicit conversions)
2) specifies that this user-defined conversion function is only considered for direct initialization (including explicit conversions)
In your case you are using direct initialization to construct an instance of type A by doing this:
A a(3.3);
The explicit keyword does not stop the compiler from implicitly casting your argument from a double type to an int. It stops you from doing something like this:
A a = 33;

C++ function overload resolution - bool vs string [duplicate]

This question already has an answer here:
String-bool comparsion - why?
(1 answer)
Closed 8 years ago.
I've found some unexpected behavior using the VC++2010 compiler with function overloading:
struct A {
A();
void O(const bool in); //(1)
void O(const std::string in);//(2)
}
Some of the following calls do not resolve like I would think:
A a;
a.O(true);//calls (1)
a.O("what?");//calls (1)
a.O(std::string("better..."));//calls (2)
Can someone explain to me why the second call resolves to the boolean function and what the motivation behind resolving in that way is?
The type of "what?" is char const[6], which after decaying to char const* while being passed into the function, is implicitly convertible to bool. The standard conversion takes precedence over user-defined implicit conversions, like the case of converting char const* to std::string.

What does A a() mean? [duplicate]

This question already has an answer here:
Most vexing parse
(1 answer)
Closed 9 years ago.
Consider this code:
#include<iostream>
using namespace std;
class A
{
public:
A():age(12){}
int age;
};
int main()
{
A a();
cout << a.age << endl;
return 0;
}
When I compile it using g++, I get an error:
you can not see the member age, because a is not a class A()
Can someone explain this to me? What is A a()?
This line
A a();
declares a function named a, returning A with no arguments. (See Most vexing parse).
What you want is
A a = A(); // value-initialization
A a{}; // the same but only valid in C++11 (and currently not supported by MSVS)
or
A a; // default initialization
C++11, §8.5/10
Note: Since () is not permitted by the syntax for initializer,
X a();
is not the declaration of a value-initialized object of class X, but the declaration of a function taking no argument and returning an X.
For your class, value-initialization == default-initialization (at least for the outcome).
See my answer here: C++: initialization of int variables by an implicit constructor for Infos on value- vs. default-initialization for POD or built-in types.
It defines a function called a that returns an object of type A. This is known as the "most vexing parse".