This may be a silly thing to ask but I am confused with compilation error while trying to use the safe bool idiom while reading this article. Below is my code and I have indicated the lines where i get errors in main() function.
// is OK case
class BoolVer_OK {
bool m_OK;
public:
BoolVer_OK(bool ok) : m_OK(ok){}
operator bool() { return m_OK; }
};
// Not OK Case
class BoolVer_NotOK {
bool m_notOK;
public:
BoolVer_NotOK(bool ok) : m_notOK(!ok){}
bool operator !() const{ reportexecution; return !m_notOK; }
};
main()
{
BoolVer_OK ok(true);
BoolVer_NotOK notOK(true);
ok<<1; // Line#1 is valid
notOK << 1; // Line#2: error: inavlid operand to binary expression ('BoolVer_notOK' and 'int')
return 0;
}
Why we didn't get error at #Line1 while we get at #Line2. Both results in a boolean value before << operator.
ok supports operator bool, and C++ has this nice functionality called implicit casting and also promotion, and in this case for the binary shift operator <<, the bool is promoted to an int, and this is then shifted by 1.
In the second case, you've not provided that operator, and hence there is nothing to implicitly convert (and promote) to int, and you get the error. Try calling !notOk before the shift, now there is a bool, which will be promoted.
I don't think the compiler would automatically insert a call to operator! and then negate that to get you the bool you want. From what I see in the link you provided, they do their tests with a double negation, !!.
ok<<1; // Line#1 is valid
notOK << 1; // Line#2: error: inavlid operand to binary expression ('BoolVer_notOK' and 'int')
This happens because ok is converted to bool implicitly (overloaded operator), whereas notOK doesn't have that operator.
Test out the following code:
BoolVer_OK ok(true);
BoolVer_NotOK notOK(true);
int z = ok<<1; // is valid
//notOK << 1; // error: inavlid operand to binary expression ('BoolVer_notOK' and 'int')
int x = false << 1;
return 0;
The booleans on the left-side of the shift operator are converted to ints and then shifted.
Related
I have next snippet
class Mapper { //not templated!
...
template<class T>
static QList<quint16> toPduValue(T value)
{
constexpr quint8 registersPerT = sizeof(T) / sizeof(quint16);
return buildPduValue((registersPerT < 1) ? (quint16) value : value);
}
template<class T>
static QList<quint16> buildPduValue(T value)
{
...
}
...
}
But when to toPduValue passed bool, and then to buildPduValue passed (quint16) value buildPduValue specializes like <int>?
callstack
debugger shows next expression
The type of your ternary expression is int. You can verify this by trying to compile this code and looking carefully at the error message:
#include <stdint.h>
char * foo = (2 < 3) ? (uint16_t)2 : (bool)1;
The error message will be something like:
error: invalid conversion from 'int' to 'char*'
You could just apply a cast to your ternary expression to cast it to the specific type you want.
Or you could ensure that both possible values of the ternary expression have the same type, so that the overall expression will have the same type.
Or you could use a if statement instead of a ternary expression.
Note that your ternary expression can only have one type; it doesn't have a different type depending on which case was evaluated.
Can someone explain me what is going on here...?
I had this code:
#include <fstream>
#include <string>
#include <iostream>
int main(){
std::ifstream file("test.txt");
std::string x;
while (true) {
if (!(file >> x)) return 0;
std::cout << x << "\n";
}
}
...compiles fine, does what it is supposed to do, no problem so far. Sometimes I dont like the ! so much, because it can be overlooked easily, so I replaced the if with
if ((file >> x)==false) return 0;
..and suddenly my compiler (gcc 4.8.5) complains with a warning:
warning: converting ‘false’ to pointer type ‘void*’ [-Wconversion-null]
if ((file >> x)==false) return 0;
and this is where I am starting to be puzzled. Where is the void* coming from? Doesnt >> return a reference that should be casted to a bool? Why is false converted to void*? Why isnt the same warning triggered when I dont explicitly write false?
Out of curiosity I also tried this:
if ((file>>x)==true) return 0;
which causes a storm of errors starting with
error: no match for ‘operator==’ (operand types are ‘std::basic_istream<char>’ and ‘bool’)
if ((file>>x)==true) return 0;
^
and now I am completely lost. How is false a differnt bool than true? Different values of course, but I always thought true and false are of same type.
Recall that C++ has operator overloads. In particular, std::basic_istream overloads operator!.
Alas, there is no enforcement that operator overloads are semantically consistent, so there is no overload for == between an istream and a bool. Thus the comparison with true fails. However, the compiler is also allowed to apply implicit conversions in order to make an expression compile - in this case false may be implicitly converted to a null pointer, and basic_istream has an overload of operator void* (though apparently that was replaced with operator bool in C++11 - presuambly to fix the inconsistency).
template<typename T> T SmartIO::Peek() {
T temp;
T tempReturn;
while(true){
temp = *(T*)&buffer[ptrSeek];
if(temp !=0){
ptrSeek++;
tempReturn += *(T*)&buffer[ptrSeek];
}
else{
break;
}
}
return tempReturn;
}
so what i want to do is , start reading from ptrSeek start looping, adding the value to temp and check if temp's value !=0 add this value to tempReturn, and once the temp's value is 0 break the loop and return the tempReturnbut, but it's keep giving me this error :
error C2678: binary '!=' : no operator found which takes a left-hand operand of type 'std::basic_string<_Elem,_Traits,_Ax>' (or there is no acceptable conversion)
how can i solve this issue here?
There is a fundamental issue with your template code if you are attempting to compare an arbitrary type T against the numeric constant 0, which you are doing in the code here:
T temp;
/* ... */
if(temp != 0){
/* ... */
}
The problem here is that T is an arbitrary type (in this case, you seem to be instantiating the template with std::string), but you are expecting that type to be comparable to 0. This is perfectly fine - it just restricts T to be types that can be compared against 0 - but from the fact that you're reporting this as an error I'm not sure if you're aware of this.
Your options are either to not instantiate this template with std::string as an argument (the way it's written, I don't think you're supposed to be able to do this, since it looks like the function keeps adding values together of some type), or to debug the template and change its behavior. I'm not quite sure what you want the code to do, so in the latter case I'm not sure how I can assist.
Hope this clarifies things!
You can specialize or overload the comparison part (here !=) for the types which are not directly comparable to 0. Just an example,
template<typename T>
bool NotEqualto0 (const T& obj) { return (obj != 0); }
// overload for std::string
bool NotEqualto0 (const std::string &s) { return (s.c_str() != 0); }
...
if(NotEqualto0(temp))
...
[Above function is hardwired for 0; it can be generalized as per need.]
there are probably several ways I will expose my ignorance with this question :)
First, I think this is C++ code, but the extension of the file is .C (so maybe it is C?)
Anyway, I am trying to compile a program called Sundance (Sentence UNDerstanding ANd Concept Extraction) which is a Natural Language Processing tool. The compile error I get relates to the following:
// This class is used internally to keep track of constituents that are
// potential subjects for clauses during clause handling.
class PotentialXP {
public:
Constituent* XPPtr;
unsigned int Distance;
unsigned int ClauseIndex;
unsigned int ConstIndex;
PotentialXP() {
XPPtr = 0;
Distance = 0;
ClauseIndex = 0;
ConstIndex = 0;
};
operator int() const {
return (int)XPPtr;
};
void Set(Constituent* w,
unsigned int x,
unsigned int y,
unsigned int z){
XPPtr = w;
Distance = x;
ClauseIndex = y;
ConstIndex = z;
};
};
The error is "cast from ‘Constituent* const*’ to ‘int’ loses precision"
and relates to the lines:
operator int() const {
return (int)XPPtr;
};
I understand why I get an error. XPPtr is of type Constituent*, so how can it be converted to an integer? Can anyone figure out what the author of the code wants to do here, and how I might rewrite this line so it compliles? What is an operator function (if that's what you call it) for?
Any advice much appreciated!
That compiles fine for me. You are on a 64-bit machine, where size_t is larger than int.
Explanation: you can historically convert a pointer an int
struct Foo {};
int main ()
{
Foo * f = new Foo ();
std :: cout << (int)f; // Prints 43252435 or whatever
}
If you want an integer which is the same size as a pointer, use size_t or ssize_t.
And why on earth are you writing operator int() like that anyway? Do you want operator bool() to test for validity? In which case a function body of return NULL != XPPtr would be better style -- clearer, at least.
The line operator int() const states a how your object can be cast to int.
The Constituent* can be cast to int because both types are usually the same size. I do not think that this is what the programmer intended, since the raw pointer value is of no semantic use. Maybe there should be a field lookup? E.g:
operator int() const {
return (int)XPPtr->somevalue;
};
I have a simple question for C.
What does this statement mean?
if (!someArray[i])
I know that the operator ! means NOT. But i cannot get my head around it.
Thank you!!
if (!someArray[i]) means if someArray[i] is zero (or convertible to false) then the code inside the if block will be executed, otherwise it will not be executed!
If someArray[i] is not convertible to boolean value OR if the type of someArray[i] doesn't define the operator ! returning boolean value (or a value convertible to it), then your code will not compile.
Note: all numbers (int, float, double, char, etc) and pointers of any type, are convertible to boolean value.
In C, it's equivalent to writing
if (someArray[i] == 0)
From the C language standard (n1256):
6.5.3.3 Unary arithmetic operators
Constraints
1 The operand of the unary + or - operator shall have arithmetic type; of the ~ operator, integer type; of the ! operator, scalar type.
Semantics
...
5 The result of the logical negation operator ! is 0 if the value of its operand compares unequal to 0, 1 if the value of its operand compares equal to 0. The result has type int. The expression !E is equivalent to (0==E).
As Kos and John Dibling pointed out, the situation in C++ is different. From the latest C++ draft (n1905)
5.3.1 Unary operators
...
8 The operand of the logical negation operator ! is implicitly converted to bool (clause 4); its value is true if the converted operand is false and false otherwise. The type of the result is bool.
It means simply that if the value in someArray[i] is interpreted as false (either a zero value, or boolean false), then the code will enter the if block.
Assume the following uncompiled/untested code:
//we make an array with some chars, but have one as NULL (0)
char someArray[] = { 'a', 'b', 'c', 0, 'e' };
//we loop through the array using i as the index
for(int i = 0; i < 5; ++i)
{
if(!someArray[i]) //if this entry is null (0) or false, show an error:
{
printf("%d does not have a char!\n", i);
}
else //otherwise, print the contents
{
printf("%d is %c\n", i, someArray[i]);
}
}
Expected output would be:
0 is a
1 is b
2 is c
3 does not have a char!
4 is e
The ! (not) operator will return true if the expression evaluates to a 0. So:
class SomeObject
{
}; // eo class SomeObject
std::vector<int> intVector;
std::vector<long> longVector;
std::vector<SomeObject*> objectVector;
intVector.push_back(1);
intVector.push_back(0);
longVector.push_back(4049);
longVector.push_back(0);
objectVector.push_back(new SomeObject);
objectVector.push_back(NULL); // or nullptr if you're on C++0x, or even just 0!
if(!intVector[0])
{
// false, intVector[0] is not zero.
}
if(!intVector[1])
{
// true! intVector[1] is zero
};
And the same holds true for the other two vectors. Incidentally, the ! operator can be overidden by a class to change the behaviour.
Note also, that this is different from C# which requires that the expression be of a boolean type:
int i = 0;
if(!i) { /* compile error in C# */ }
if(i == 0) { /* ok in C# */ }
bool b = false;
if(!b) { /* ok in C# */ }
if(!(i == 0)) { /* also ok */ }
Perhaps the important thing to know about in the statement if (!someArray[i]) is the precedence of the operators.
first [ is evaluated, then ! is evaluated.
Writing it in a longer form might be
sometype a = someArray[i];
if(!a)