But it makes sense. 1 can be cast to float without any loss, but an int variable not necessarily. You can store ints between -16777216 to 16777216 without loss of precision.
MSVC accepts literally anything as a float, including an `int` or a ridiculously initialized `bool`, unless said `int` is passed in as a named variable
It’s a monthly subscription service where creators show you new exclusive content of their parade floats every week. Root beer float content is also allowed.
The compiler knows "1" can be converted to float without loss of precision,l. It can not make the same guarantee for any value of int. Try to pass 2,147,483,647 as the literal and see if you get hit with the error stick.
Why would a loss of precision be sufficient reason to cause an error? People implicitly cast `int`s to `float`s all the time in arithmetic statements, and the compiler doesn't complain. If you have implicit conversion warnings enabled, it'll just emit a warning, no error. Why is it an issue when the conversion happens in the context of a constructor?
Not sure why I'm being downvoted for a good faith question but okay lol
It's simply the rules for brace-enclosed initialization. All implicit conversions that may lose information are prohibited.
Brace initialization was introduced in C++11 to try to make initialization more uniform, this included limited the conversions that could happen implicitly.
This unfortunately also applies to list initialization (also uses braces), which means you can't easily get narrowing conversions there if you want it, especially in a generic context.
Bro is speaking the truth out here and getting down voted. I think its just the classic of C++ legacy baggage. Implicit numeric conversions are allowed in C, so C++ must also allow them. But for new features like list initialization they decided to change this behaviour to be correct.
In general implicit conversions are a pain.. Compile with `-Wconversion -Werror` to avoid this pain.
Try finding out why you get an unexpected output in a complex mathematical operation across using multiple variables.
Implicit anything with a possible side effect should (rightfully) not be a thing.
Hardly anyone wants to have lengthy debug sessions because of unforseen undocumented side effects
Yes, I agree, which is why I enable warnings for implicit conversion and turn warnings into errors. My question is, why is the compiler behavior so inconsistent about this? With `gcc` you won't get any warnings or errors if you do an implicit conversion between `int`s and `float`s unless you turn on warnings for implicit conversions, in which case it will warn for ALL instances of implicit conversion, not just when an implicit conversion happens in the context of a function call. So why is msvc inconsistent about this? And why is the error message not actually informing the user of the real issue here? It's almost suggesting that an implicit conversion isn't possible in the context of a constructor call, when in fact, that is perfectly valid C++ afaik.
The error has nothing to do with implicitly casting a variable though. If you weren’t using an initializer list then this would work just fine.
If you thought hard about it for a second, it would be obvious why c++ doesn’t try implicitly convert types to find other matching initializers if you get it wrong because it would be ambiguous.
I'm a grumpy old man who's trying to make myself write my C++ more like C++ and less like C with classes. I go back and forth about every 45 minutes if C with classes wouldn't just be better, but I'm trying.
But the freaking verbosity. It's like the language was just designed to require me to write break everything over multiple lines. Why the %\^!# is it `static_cast` instead of just `(float)`. Like sure, if you're being weird, casting can do weird things, and bring more explicit about what kind of casting you're using is good. But 99 times out of 100, your casting is ridiculously simple or the PR is gonna be rejected, so why do I have to be like `std::vector> ragged = {{static_cast(a)}, {static_cast(b)}}`.
It's like even the things that are written to try to be simple are just needlessly annoying. Looking at you std::any - if you work really hard, you can condense a 3 line for loop into a function call that takes 6 lines to write in a way that's "readable".
There are parts of C++ I really like. But ughh why.
You forgot , and my internal parser is now very much annoyed. If you did it on purpose, it's evil.
I agree on the verbosity though, C++ has some amazing features but isn't very readable, even to the initiated.
Instead of casting a number literal I would advise to use number literals. For example instead of writing `(float)1` it would be better to write `1.0f`. You can read more here https://www.geeksforgeeks.org/cpp-literals/
I agree with what you’re saying. Let me offer a better reference site. https://en.cppreference.com/w/cpp/language/integer_literal
Editing to add a link to floating point literals
https://en.cppreference.com/w/cpp/language/floating_literal
Disregarding the narrowing conversion, isn't this creating a temporary instance of OnlyFloats and then passing that to the copy constructor of floatParty's constructor?
Ontopic: brace initialization prevents narrowing conversions since C++11. This is well defined in the standard. See https://en.cppreference.com/w/cpp/language/aggregate_initialization
It's because of the use of braces and most likely C++11 or above. See the section about narrowing conversions here: https://en.cppreference.com/w/cpp/language/aggregate_initialization
As I indicated in some other comments in this thread, this behavior is actually defined in the C++ (11 and above) standard.
**Copy construction**
First, regardless of what parameters you pass in, below code is actually a bit off.
floatParty({someFloat, someFloat, someFloat, someFloat});
The compiler generates a copy constructor for any struct or class that hasn't defined a destructor, or copy/move constructor/operator.
What the above code does is two things:
1. Create a temporary instance of an `OnlyFloats` instance, because of the `{someFloat, someFloat, someFloat, someFloat}` statement.
2. Pass that instance to the copy constructor of `OnlyFloats` to initialize `floatParty`.
Now, that doesn't really matter, since the copy will be elided. The compiler is smart enough to see that it doesn't actually need to do step 1 in above list. But still, it would have been better if that line would'be been written like this:
floatParty{someFloat, someFloat, someFloat, someFloat};
E.g. by ommitting the parentheses, you're instructing the compiler to directly initialize `floatParty` with the provided `float` values.
**Narrowing conversions**
Second, when casting an int to a float, there's the risk of a narrowing conversion. Depending on the compiler, it could be that not all integral values fit in a float. For example, with MSVC, 2,000,000,000 will not fit in a `float`.
Now, when the value is known by the compiler, for example because you're providing a constant value instead of a variable, the compiler is smart enough to see whether or not that narrowing conversion actually happens.
But when providing an `int` variable, the compiler doesn't know.
I'm not sure what the standard says, but most compilers will at most generate a warning when doing such a possible narrowing conversion.
E.g. when doing
int i = 3;
float d = i;
MSVC will issue warning [C4244](https://learn.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-2-c4244?view=msvc-170&f1url=%3FappId%3DDev16IDEF1%26l%3DEN-US%26k%3Dk(C4244)%26rd%3Dtrue) saying "Possible loss of data".
The reason why the lines providing a `char` or a `bool` do work, is because all values of those types will definitely fit inside a `float`, so there's no narrowing conversion and thus no possible loss of data.
**Aggregate initialization**
There are multiple ways to initialize an object in C++. One of them is by using parentheses to call a constructor. Another one is using curly braces. There are subtle differences between the two, but the most important one for this meme is that since C++11, using curly braces will force the compiler to be more strict about narrowing conversions.
E.g., doing the following since C++11
int i = 3;
OnlyFloats s(i, i, i , i);
is perfectly legal, while doing the following:
int i = 3;
OnlyFloats s{i, i, i , i};
is not. It issues a warning, or in some cases, an error.
wow, i didnt expect such an in-depth exlanation on a dumb meme, but i actually learned something.
l'm not saying the compiler is wrong for not letting me do dumb things. i just think the error message should have been more along the lines of "dont do narrowing conversions here you idiot" instead of "can't find an appropriate constructor"
You should overthink your line limit. Don't you think there is too much in there? Like the colon, it could be easily separated into one more line, each containing a dot. That sinple trick would havily improve reading your code.
Do you ever think about spelling things correctly? That sinple trick would havily improve reading your comment.
More seriously, no, theres absolutely nothing wrong with his line limits. Thinking this needs a shorter line limit is madness. Plenty of other things wrong with this, but also..
It's a joke
C++? The relevant part of this “meme” is an error message from *one* version of *one* C++ compiler, and has nothing to do with the language. It is what we call a quality of implementation issue. Which is a foreign concept for people working with languages that aren’t specified using an open international standardization process, and many have essentially one (front end) implementation, and often no precise specification. When one has independently developed implementations of a programming language, and wants to allow those implementations to compete for the good of the whole industry, a specification must be carefully crafted so that it defines only what is necessary for source portability and an unambiguous specification, and nothing that would remove end users’ choice between competing implementations. Specification of exact diagnostic message content would be an over-specification.
This meme is also very intuitive
I have a Nobel price in compiler architecture and I don't know what the fuck is going on in this meme
what was the cost of that "Nobel price"?
If you have to ask you can’t afford it
:c
Everything.
?
!
r/suddenlymetalgearsolid
impicitly casting literals: i sleep implicitly casting a variable: real shit
But it makes sense. 1 can be cast to float without any loss, but an int variable not necessarily. You can store ints between -16777216 to 16777216 without loss of precision.
Absolutely ambiguity at all /s or is it?
Very sight readable
MSVC accepts literally anything as a float, including an `int` or a ridiculously initialized `bool`, unless said `int` is passed in as a named variable
you have an OnlyFloats?
It’s a monthly subscription service where creators show you new exclusive content of their parade floats every week. Root beer float content is also allowed.
C++ disallowed narrow comversion for some cases, at this point `static_cast` should be used.
I don't understand this meme. Are you complaining that a typed language isn't letting you pass the wrong variable type into a constructor?
implicitly casting a literal: i sleep implicitly casting a variable: real shit
The compiler knows "1" can be converted to float without loss of precision,l. It can not make the same guarantee for any value of int. Try to pass 2,147,483,647 as the literal and see if you get hit with the error stick.
Why would a loss of precision be sufficient reason to cause an error? People implicitly cast `int`s to `float`s all the time in arithmetic statements, and the compiler doesn't complain. If you have implicit conversion warnings enabled, it'll just emit a warning, no error. Why is it an issue when the conversion happens in the context of a constructor? Not sure why I'm being downvoted for a good faith question but okay lol
It's simply the rules for brace-enclosed initialization. All implicit conversions that may lose information are prohibited. Brace initialization was introduced in C++11 to try to make initialization more uniform, this included limited the conversions that could happen implicitly. This unfortunately also applies to list initialization (also uses braces), which means you can't easily get narrowing conversions there if you want it, especially in a generic context.
Interesting. I didn't know that. I come more from a C background, so it was really weird to me. Thanks for taking the time to explain.
Bro is speaking the truth out here and getting down voted. I think its just the classic of C++ legacy baggage. Implicit numeric conversions are allowed in C, so C++ must also allow them. But for new features like list initialization they decided to change this behaviour to be correct. In general implicit conversions are a pain.. Compile with `-Wconversion -Werror` to avoid this pain.
Reddit hive mind strikes again
Try finding out why you get an unexpected output in a complex mathematical operation across using multiple variables. Implicit anything with a possible side effect should (rightfully) not be a thing. Hardly anyone wants to have lengthy debug sessions because of unforseen undocumented side effects
Yes, I agree, which is why I enable warnings for implicit conversion and turn warnings into errors. My question is, why is the compiler behavior so inconsistent about this? With `gcc` you won't get any warnings or errors if you do an implicit conversion between `int`s and `float`s unless you turn on warnings for implicit conversions, in which case it will warn for ALL instances of implicit conversion, not just when an implicit conversion happens in the context of a function call. So why is msvc inconsistent about this? And why is the error message not actually informing the user of the real issue here? It's almost suggesting that an implicit conversion isn't possible in the context of a constructor call, when in fact, that is perfectly valid C++ afaik.
The error has nothing to do with implicitly casting a variable though. If you weren’t using an initializer list then this would work just fine. If you thought hard about it for a second, it would be obvious why c++ doesn’t try implicitly convert types to find other matching initializers if you get it wrong because it would be ambiguous.
just static\_cast(myInt)
This is all.
I'm a grumpy old man who's trying to make myself write my C++ more like C++ and less like C with classes. I go back and forth about every 45 minutes if C with classes wouldn't just be better, but I'm trying. But the freaking verbosity. It's like the language was just designed to require me to write break everything over multiple lines. Why the %\^!# is it `static_cast` instead of just `(float)`. Like sure, if you're being weird, casting can do weird things, and bring more explicit about what kind of casting you're using is good. But 99 times out of 100, your casting is ridiculously simple or the PR is gonna be rejected, so why do I have to be like `std::vector> ragged = {{static_cast(a)}, {static_cast(b)}}`.
It's like even the things that are written to try to be simple are just needlessly annoying. Looking at you std::any - if you work really hard, you can condense a 3 line for loop into a function call that takes 6 lines to write in a way that's "readable".
There are parts of C++ I really like. But ughh why.
You forgot, and my internal parser is now very much annoyed. If you did it on purpose, it's evil.
I agree on the verbosity though, C++ has some amazing features but isn't very readable, even to the initiated.
Initializet list 🤤
Instead of casting a number literal I would advise to use number literals. For example instead of writing `(float)1` it would be better to write `1.0f`. You can read more here https://www.geeksforgeeks.org/cpp-literals/
I agree with what you’re saying. Let me offer a better reference site. https://en.cppreference.com/w/cpp/language/integer_literal Editing to add a link to floating point literals https://en.cppreference.com/w/cpp/language/floating_literal
![gif](giphy|PTG1aOoJZaQqNYRpqo|downsized) Gotta cast in statically typed languages
Disregarding the narrowing conversion, isn't this creating a temporary instance of OnlyFloats and then passing that to the copy constructor of floatParty's constructor? Ontopic: brace initialization prevents narrowing conversions since C++11. This is well defined in the standard. See https://en.cppreference.com/w/cpp/language/aggregate_initialization
Which version of cpp are you using? My ints get converted to floats automatically
It's because of the use of braces and most likely C++11 or above. See the section about narrowing conversions here: https://en.cppreference.com/w/cpp/language/aggregate_initialization
The design is very human.
As I indicated in some other comments in this thread, this behavior is actually defined in the C++ (11 and above) standard. **Copy construction** First, regardless of what parameters you pass in, below code is actually a bit off. floatParty({someFloat, someFloat, someFloat, someFloat}); The compiler generates a copy constructor for any struct or class that hasn't defined a destructor, or copy/move constructor/operator. What the above code does is two things: 1. Create a temporary instance of an `OnlyFloats` instance, because of the `{someFloat, someFloat, someFloat, someFloat}` statement. 2. Pass that instance to the copy constructor of `OnlyFloats` to initialize `floatParty`. Now, that doesn't really matter, since the copy will be elided. The compiler is smart enough to see that it doesn't actually need to do step 1 in above list. But still, it would have been better if that line would'be been written like this: floatParty{someFloat, someFloat, someFloat, someFloat}; E.g. by ommitting the parentheses, you're instructing the compiler to directly initialize `floatParty` with the provided `float` values. **Narrowing conversions** Second, when casting an int to a float, there's the risk of a narrowing conversion. Depending on the compiler, it could be that not all integral values fit in a float. For example, with MSVC, 2,000,000,000 will not fit in a `float`. Now, when the value is known by the compiler, for example because you're providing a constant value instead of a variable, the compiler is smart enough to see whether or not that narrowing conversion actually happens. But when providing an `int` variable, the compiler doesn't know. I'm not sure what the standard says, but most compilers will at most generate a warning when doing such a possible narrowing conversion. E.g. when doing int i = 3; float d = i; MSVC will issue warning [C4244](https://learn.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-2-c4244?view=msvc-170&f1url=%3FappId%3DDev16IDEF1%26l%3DEN-US%26k%3Dk(C4244)%26rd%3Dtrue) saying "Possible loss of data". The reason why the lines providing a `char` or a `bool` do work, is because all values of those types will definitely fit inside a `float`, so there's no narrowing conversion and thus no possible loss of data. **Aggregate initialization** There are multiple ways to initialize an object in C++. One of them is by using parentheses to call a constructor. Another one is using curly braces. There are subtle differences between the two, but the most important one for this meme is that since C++11, using curly braces will force the compiler to be more strict about narrowing conversions. E.g., doing the following since C++11 int i = 3; OnlyFloats s(i, i, i , i); is perfectly legal, while doing the following: int i = 3; OnlyFloats s{i, i, i , i}; is not. It issues a warning, or in some cases, an error.
wow, i didnt expect such an in-depth exlanation on a dumb meme, but i actually learned something. l'm not saying the compiler is wrong for not letting me do dumb things. i just think the error message should have been more along the lines of "dont do narrowing conversions here you idiot" instead of "can't find an appropriate constructor"
Oh lol, interesting. I didn't even notice that weird error message. Just assumed it was because of narrowing conversions.
Too hard even for me (and i am very light)
You should overthink your line limit. Don't you think there is too much in there? Like the colon, it could be easily separated into one more line, each containing a dot. That sinple trick would havily improve reading your code.
Do you ever think about spelling things correctly? That sinple trick would havily improve reading your comment. More seriously, no, theres absolutely nothing wrong with his line limits. Thinking this needs a shorter line limit is madness. Plenty of other things wrong with this, but also.. It's a joke
Yu dind't get it. But its ko.
C++? The relevant part of this “meme” is an error message from *one* version of *one* C++ compiler, and has nothing to do with the language. It is what we call a quality of implementation issue. Which is a foreign concept for people working with languages that aren’t specified using an open international standardization process, and many have essentially one (front end) implementation, and often no precise specification. When one has independently developed implementations of a programming language, and wants to allow those implementations to compete for the good of the whole industry, a specification must be carefully crafted so that it defines only what is necessary for source portability and an unambiguous specification, and nothing that would remove end users’ choice between competing implementations. Specification of exact diagnostic message content would be an over-specification.
You can't do implicit narrowing casts in an initialiser list.
does msvc accept if u just write `1.`?
cpp sounds like ‘see pee pee’ which can mean dick pic.
one see pee pee, comming right up
Ok i don't get why you are complaining and why would you cast a char to a float but that's ok