Ternary operator - c++

Is there any logical reason that will explain why in ternary optor both branches must have the same base type or be convertible to one? What is the problem in not having this rule? Why on earth I can't do thing like this (it is not the best example, but clarifies what I mean):
int var = 0;
void left();
int right();
var ? left() : right();

Expressions must have a type known at compile time. You can't have expressions of type "either X or Y", it has to be one or the other.
Consider this case:
void f(int x) {...}
void f(const char* str) {...}
f(condition ? 5 : "Hello");
Which overload is going to be called? This is a simple case, and there are more complicated ones involving e.g. templates, which have to be known at compile time. So in the above case, the compiler won't choose an overload based on the condition, it has to pick one overload to always call.
It can't do that, so the result of a ternary operator always has to be the same type (or compatible).

The ternary operator returns the value of the branch it takes. If the two branches didn't both have the same type, the expression would have an indeterminate type.

The point is that an expression should have a statically defined type.
If branches of your ternary operator are incompatible, you cannot statically deduce the ternary expression type.

I guess because the ternary operator must have a defined return value. Hard to do if the types of both branches is different, or void.

Related

Why it shows error: expected expression before ‘return’?

#include<stdio.h>
int main(void)
{
int x=1,y=0;
x>y?printf("Hello World"):return x;
}
Why it shows error: expected expression before ‘return’?
What is the thing need to be changed here?
Why it shows error: expected expression before ‘return’?
The ternary operator is an operator, requiring three operands. The first operand must be an expression of integer type. The latter two operands must be expressions of type compatible with each other.
A return statement specifies a return value for the function in which it appears, and causes that function to terminate. It is not an expression, and does not evaluate to a value, neither the specified return value or any other. As such, it cannot be an operand of the ternary operator.
The error message is, therefore, expressing that the third operand of the ternary operator is missing, which it is, since the return statement cannot be considered an operand. If it were present, that operand would appear before the return.
What is the thing need to be changed here?
To obtain the logic you appear to want, the thing to change is the ternary operator. Use an if / else statement instead:
if (x > y) {
printf("Hello World");
} else {
return x;
}
Generally speaking, the ternary operator should be avoided. It usually makes code harder to read and understand, with little or no offsetting benefit. You may someday discover a programming context where a ternary is the cleanest, clearest way to go, but anywhere else, use if.
The main theme of the ternary operator is
condition ? value_if_true : value_if_false
The statement evaluates to value_if_true if the condition is met, and value_if_false otherwise.
Read more about 'ternary operator' [https://www.freecodecamp.org/news/c-ternary-operator/]
Try to avoid a ternary operator if your concept is not clear. Try to use if-else.

How to use a Caret "^" in C++ for Exponentiation

I am currently rewriting MATLAB code into C++ code. To have the ability to raise "a" to the power of "b" just by typing "a^b" would make my life so much easier as this is how much of the original code was written in MATLAB.
Is there a way to do this? (I am using primitive types)
I'll happily accept a solution that does NOT involve parenthesis and commas like the pow(a,b) method.
Thanks in advance.
While it is possible to overload ^ to do exponentiation, you shouldn't. It's a bad idea.
#AaronF's answer shows how ugly the code to do this is, but that's only the tip of the iceberg. The real problem comes when you try to actually use this in real code. The problems stem from one simple fact: overloading an operator changes the actions carried out by that operator, but does not affect either the precedence or associativity of that operator. In the case of ^, both the precedence and the associativity are completely wrong for exponentiation.
precedence
In C++, the ^ operator has quite low precedence. Exponentiation should have very high precedence. For example, an expression like x^y*z would normally mean xyz--but what it will mean in C++ is xyz. In fact in C++, ^ has precedence even lower than addition and subtraction, so even x^y+z comes out wrong--it means xy+z instead of the xy+z that you'd want/normally expect.
Associativity
Exponentiation is right associative--but in C++, the ^ operator is left associative. For example, given an expression like x^y^z, what you'd want/expect would be for it to mean xyz, but what you'll get is (xy)z (equivalent to xyz).
Result
These mean that if you do overload operator^ to do exponentiation, you'll only have gotten away from using the name pow. You will not get away from most of the parentheses; in any non-trivial expression, you'll still need parentheses to force the proper precedence and associativity, because as outlined above, the precedence and associativity C++ assigns to operator^ are both entirely wrong for exponentiation.
Conclusion
Although you can overload operator^ to do exponentiation, this is one of those places where discretion is the better part of valor. When you overload operators in C++, you really have three factors to take into account: the name, the precedence and the associativity. For a good operator overload, all three should be right. It's sometimes reasonable to do an overload where only two out of three are right, and the third isn't too far off. In this case, only one out of the three is even close to right; the other two are completely wrong.
Don't do this. It's a bad idea.
The following works, but you have to compile with the c++11 standard (g++ -std=c++11 *.cpp):
You can't use the XOR (^) operator for exponents with primitives. You have to overload it within a class.
#include <iostream>
#include <cmath>
#include <ctgmath>
using namespace std;
class Number {
private:
float _num;
public:
Number(float num) : _num(num){}
Number operator^(const float& num) {
return Number(pow(_num,num));
}
float get() {
return _num;
}
};
int main() {
Number a = Number(5);
Number b = a^7;
cout << b.get();
}
For primitive types (your case) :
In C and in C++, ^ is the bitwise XOR (exclusive-or) operator.
You should use std::pow to raise a number to a power.
For non primitive types, you could however overload operator^ (but it is discouraged since you would go against the usual meaning of this operator)
Example:
MyClass operator^(const MyClass& t1, const MyClass& t2)
{
//return ...
}
You can't do this for primitive types. You'll need to use std::pow. You can do it for user-defined types by overloading the ^ operator, but it may not be a good idea unless XOR makes no sense for your type.
(10 minutes after I say this someone will come up with a horrible, horrible hack for primitive types with a user-defined type, implicit conversions, a user-defined literal, and an overloaded ^ operator.)
pow() in the cmath library. More info on
http://en.cppreference.com/w/cpp/numeric/math/pow
it seems you are looking for someone to say write a^b :D
you should use predefined functions or write a new one ;)

Compile-time assert using templates in c++

I was reading code from the cpp-btree library of google (https://code.google.com/p/cpp-btree/) and I came accross that compile-time assert mechanism.
// A compile-time assertion.
template <bool>
struct CompileAssert {
};
#define COMPILE_ASSERT(expr, msg) \
typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
So I understand more or less what it does, if expr is evaluated to false by the compiler it will declare a new type msg that will be a CompileAssert < false > array of size -1 which will trigger a compilation error.
What I don't get is the bool(expr) part, what is this exactly? Some kind of call to the copy constructor of the class bool? (but it's a builtin type so I'm confused)
I though this would be a mechanism to raise a compilation error when expr is not a boolean but actually I managed to compile a short program whit that line
COMPILE_ASSERT("trash",error_compilation_assert);
It compiles just fine with gcc 3.4
So can anyone explain the bool(expr) part of the mechanism?
It's a type conversion. There are 3 main types of type conversions in C++:
Cast notation (C-style cast): (bool) expr
Functional notation (constructor-style cast): bool(expr)
Cast operators (C++-style cast); static_cast<bool>(expr)
Cast notation and functional notation are semantically equivalent (i.e. they both perform the strongest possible conversion, the C-cast), but the scope & precedence of the functional notation is clearer.
It is generally advised not to use them in C++ code and use the specific cast operators (const_cast, static_cast etc.) instead.
So in your code, it's just a way of forcing the value to type bool and enclosing it in parentheses at the same time, so that no operator priority issues arise.
bool(expr) casts expr into a bool.
The first parameter should be some kind of expression, such as a == b. Using a string literal here is useless.
bool(expr) is a function-style cast which converts the expression to a bool. Lots of things convert implicitly to bool, but I guess they wanted an explicit cast to make sure the result is a bool.
If you convert a pointer to a bool, it evaluates to false if it is a NULL pointer, or true otherwise. Your string literal "Trash" decays into a const char * to the first character. As this is not a null pointer, the expression evaluates to true.
bool(expr) tries to convert expr to bool either implicitly or using any user defined conversion operator.
In C++, you can instantiate built-in types with ctor syntax:
bool b1 = bool(true);
bool b2 = bool(b1);
The difference to:
bool b2 = b1;
is that the latter does an implicit conversion to bool. When such an implicit conversion isn't allowed (as in the template typedef), then bool(b1) makes it explicit by creating a temporary bool from b1 and the temporary doesn't have to be converted anymore; it's an actual bool type.

Conversion function for error checking considered good?

I'd like to have a simple way of checking for an object to be valid. I thought of a simple conversion function, something like this:
operator bool() const { return is_valid; }
Checking for it to be valid would be very simple now
// is my object invalid?
if (!my_object) std::cerr << "my_object isn't valid" << std::endl;
Is this considered a good practise?
In C++03, you need to use the safe bool idiom to avoid evil things:
int x = my_object; // this works
In C++11 you can use an explicit conversion:
explicit operator bool() const
{
// verify if valid
return is_valid;
}
This way you need to be explicit about the conversion to bool, so you can no longer do crazy things by accident (in C++ you can always do crazy things on purpose):
int x = my_object; // does not compile because there's no explicit conversion
bool y = bool(my_object); // an explicit conversion does the trick
This still works as normal in places like if and while that require a boolean expression, because the condition of those statements is contextually converted to bool:
// this uses the explicit conversion "implicitly"
if (my_object)
{
...
}
This is documented in §4[conv]:
An expression e can be implicitly
converted to a type T if and only if
the declaration T t=e; is well-formed,
for some invented temporary variable t
(§8.5). Certain language constructs
require that an expression be
converted to a Boolean value. An
expression e appearing in such a
context is said to be contextually converted to bool and is well-formed
if and only if the declaration bool t(e); is well-formed, for some
invented temporary variable t (§8.5). The effect of either
implicit conversion is the same as performing the
declaration and initialization and then using the temporary
variable as the result of the conversion.
(What makes the difference is the use of bool t(e); instead of bool t = e;.)
The places were this contextual conversion to bool happens are:
the conditions of if, while, and for statements;
the operators of logical negation !, logical conjunction &&, and logical disjunction ||;
the conditional operator ?:;
the condition of static_assert;
the optional constant expression of the noexcept exception specifier;
No, a simple bool conversion operator is not, as you can now make evil comparisions between unrelated types. Generally, yes, a conversion function is a-okay. Just use the right one (safe-bool idiom). I can't explain it any better than the given links.
The original question was
Is this considered a good practise?
The issue with the safe bool conversion was very relevant in practice, but fortunately has now been addressed by the standards.
But the judgement if this approach is appropriate, is a question of design.
By introducing such a "validity check", effectively you are stating that your objects can be in an invalid state. That is, speaking in the terms of computer science, you added a new separate value to the value domain represented by your objects. A so called bottom value
The most prominent example for a value domain with that propery is the pointer. A pointer can refer to various memory locations, but it also can be NULL (invalid).
Thus we need do ask ourselves: does such a bottom value really reflect the nature of the things we want to model with our classes -- and -- do we really need to cover this aspect of the nature within our model?
Experience shows that bottom values tend to be error prone, easy to forget and generally more of a liability than an asset. If you're able to arrange your code in a way that your objects can not be invalid, your code gets simpler, easier to read, to understand and to maintain..

Odd behavior with operator>= overloading

I'm having a strange behavior with an operator overloading in C++. I have a class, and I need to check if its contents are greater or equal to a long double. I overloaded the >= operator to make this check, my declaration is as follows:
bool MyClass::operator>=(long double value) const;
I have to say that I also have a cast-to-long-double operator for my class, that works without exceptions only under certain conditions.
Now, when I use this operator, the compiler complains that there's an ambiguous use of operator>= and the alternatives are:
Mine.
The built-in operator>=(long double, int).
Now, how do I force the program to use my operator?
2015 update: Or, if you want to keep conversion ability using the (double)obj syntax instead the obj.to_double() syntax, make the conversion function explicit by prefixing it with that keyword. You need an explicit cast then for the conversion to trigger. Personally, I prefer the .to_double syntax, unless the conversion would be to bool because in that case the conversion is used by if(obj) even if it is explicit, and that is considerably more readable than if(obj.to_bool()) in my opinion.
Drop the conversion operator. It will cause troubles all the way. Have a function like
to_double()
Or similar that returns the double value and call that function explicitly to get a double.
For the problem at hand, there is this problem:
obj >= 10
Consider that expression. The builtin operator matches the first argument by a user defined conversion sequence for your type using the conversion operator long double(). But your function matches the second argument by a standard conversion sequence from int to long double (integral to floating point conversion). It is always ambiguous when there are conversions for two arguments, but not at least one argument that can be converted better while the remaining arguments are not converted worse for one call. In your case, the builtin one matches the second argument better but the first worse, but your function matches the first argument better but the second worse.
It's confusing, so here are some examples (conversions from char to int are called promotions, which are better than conversions from char to something other than int, which is called a conversion):
void f(int, int);
void f(long, long);
f('a', 'a');
Calls the first version. Because all arguments for the first can be converted better. Equally, the following will still call the first:
void f(int, long);
void f(long, long);
f('a', 'a');
Because the first can be converted better, and the second is not converted worse. But the following is ambiguous:
void f(char, long);
void f(int, char);
f('a', 'a'); // ambiguous
It's more interesting in this case. The first version accepts the first argument by an exact match. The second version accepts the second argument by an exact match. But both versions do not accept their other argument at least equally well. The first version requires a conversion for its second argument, while the second version requires a promotion for its argument. So, even though a promotion is better than a conversion, the call to the second version fails.
It's very similar to your case above. Even though a standard conversion sequence (converting from int/float/double to long double) is better than a user-defined conversion sequence (converting from MyClass to long double), your operator version is not chosen, because your other parameter (long double) requires a conversion from the argument which is worse than what the builtin operator needs for that argument (perfect match).
Overload resolution is a complex matter in C++, so one can impossibly remember all the subtle rules in it. But getting the rough plan is quite possible. I hope it helps you.
By providing an implicit conversion to a double you are effectively stating, my class is equivalent to a double and for this reason you shouldn't really mind if the built in operator >= for doubles is used. If you do care, then your class really isn't 'equivalent' to a double and you should consider not providing an implicit conversion to double, but instead providing an explicit GetAsDouble, or ConvertToDouble member function.
The reason that you have an ambiguity at the moment is that for an expression t >= d where t is an instance of your class and d is a double, the compiler always has to provide a conversion of either the left hand side or the right hand side so the expression really is ambiguous. Either t's operator double is called and the built-in operator >= for doubles is used, or d must be promoted to a long double and your member operator >= is used.
Edit, you've updated your question to suggest that your conversion is to long double and your comparison is against an int. In which case the last paragraph should read:
The reason that you have an ambiguity at the moment is that for an expression t >= d where t is an instance of your class and d is an int, the compiler always has to provide a conversion of either the left hand side or the right hand side so the expression really is ambiguous. Either t's operator long double is called and the built-in operator >= for long double and int is used, or d must be promoted to a long double and your member operator >= is used.
I assume you are comparing against a literal int, and not a long double:
MyClass o;
if (o >= 42)
{
// ...
}
If that is the case both alternatives are as good/complex.
Using your operator long double():
MyClass::operator long double()
built-in operator>=(long double, int)
Using your MyClass::operator>=(long double):
built-in conversion int to long double
MyClass::operator>=(long double)
You've got long double in the declaration. Try changing it to double.
Your use of operator overloading combined with custom casting can be very confusing to users of your class. Ask yourself, would users of this class expect it to convert itself into a double, or be comparable with a double? Wouldn't having a .greaterThan(double) function achieve the same goal but without surprising the user?
I guess you could always explicitly cast your object to double before comparing, to avoid the ambiguity. But if I were you I'd reconsider the approach above and focus on writing code that's intuitive and behaves in an unsurprising manner, instead of fancy type-casting and operator overloading.
(Inspired by the FQA's wonderful rant about operator overloading)
The built-in operator>=(long double, int).
Looks like you've defined:
bool class::operator>=(long double value) { return value >= classValue; }
And you are missing:
bool class::operator>=(double value) { return value >= classValue; }
bool class::operator>=(int value) { return value >= classValue; }
So the compiler can't decide which way to convert. (It's ambiguous.)
Perhaps a templated function (or method) would be helpful?
Watch out for situations where a>=b invokes different methods than b>=a.