I have this code and I searched for hours why it fails to print my income
int const income = 0;
std::cout << "I'm sorry, your income is: " < income;
Until I found I missed to write << but wrote <. Why doesn't the compiler detect this and error out? I'm not sure why comparing cout makes sense?
integral constant 0 is also a null pointer constant - it can be compared to the result of ostream's operator void *. Note that it'll fail if the constant has any value but 0.
The prototypes of the < operator are like :
bool T::operator <(const T& b) const;
So I guess the compiler transtype the argument as the type of this instance.
Did you enabled all the warnings like -Wall
It does compile with g++ 4.4.3
#include <iostream>
int main (void)
{
int const income = 0;
std::cout << "I'm sorry, your income is: " < income;
}
However, when running it with -Wall (good practice!), I got a funny message:
:~/stack$ g++ test.cpp -o temp
:~/stack$ g++ -Wall test.cpp -o temp
test.cpp: In function 'int main()':
test.cpp:5: warning: right-hand operand of comma has no effect
No clue what it actually does (or tries to do)...
When I compile this code using GCC 4.3.4, I see a warning:
prog.cpp: In function ‘int main()’:
prog.cpp:6: warning: right-hand operand of comma has no effect
...though why it's a warning rather than an error, I don't know.
EDIT: In fact, I don't know which comma it's referring to either, because this code:
int const income = 0;
std::cout << "I'm sorry your income is: " < income;
...generates the same warning (see here).
Related
I read in the C++17 Standard $8.5.7.4:
The expression E1 is sequenced before the expression E2.
for shift operators.
Also cppreference rule 19 says:
In a shift operator expression E1<>E2, every value computation and side-effect of E1 is sequenced before every value computation and side effect of E2
But when I try to compile the following code with gcc 7.3.0 or clang 6.0.0
#include <iostream>
using namespace std;
int main() {
int i = 5;
cout << (i++ << i) << endl;
return 0;
}
I get the following gcc warning:
../src/Cpp_shift.cpp: In function ‘int main()’:
../src/Cpp_shift.cpp:6:12: warning: operation on ‘i’ may be undefined [-Wsequence-point]
cout << (i++ << i) << endl;
~^~
The clang warning is:
warning: unsequenced modification and access to 'i' [-Wunsequenced]
I used the following commands to compile:
g++ -std=c++17 ../src/Cpp_shift.cpp -o Cpp_shift -Wall
clang++ -std=c++17 ../src/Cpp_shift.cpp -o Cpp_shift -Wall
I get the expected 320 as output in both cases ( 5 * 2 ^ 6 )
Can someone explain why I get this warning? Did I overlook something? I also read this related question, but it does not answer my question.
edit: all other variants ++i << i, i << ++i and i << i++ result in the same warning.
edit2: (i << ++i) results in 320 for clang (correct) and 384 for gcc (incorrect). It seems that gcc gives a wrong result if the ++ is at E2, (i << i++) also gives a wrong result.
Standard is clear about the order of evaluation of the operands of the shift operator.
n4659 - §8.8 (p4):
The expression E1 is sequenced before the expression E2.
There is no undefined behavior in the expression i++ << i, it is well defined. It is a bug in Clang and GCC both.
I look for a warning compilation flag of g++ that will prevent silent conversion from bool to double.
This answer relates to a broader question of conversion of int to double. The question was dismissed there because it's considered a lossless conversion and perfectly legal.
However, since bool has another semantic meaning than simple integer, I expect that an implicit conversion from bool to double will issue a warning.
I've tried:
-Wall -Wextra -pedantic -Wconversion
on the following code without any success (no warning issued):
#include <iostream>
int foo(double var){
return static_cast<int>(var);
}
int main(){
std::cout << foo(5) << std::endl;
std::cout << foo(5.1) << std::endl;
std::cout << foo(false) << std::endl; // here I want the warning
return 0;
}
I use g++ 4.9.2, but an answer suggesting using higher version is perfectly acceptable.
Thanks.
This is an approach that has nothing to do with gcc, but instead relies on another tool: clang-tidy has a readability-implicit-bool-conversion check that will warn you in this case. You need a separate static analysis check (which might take long to run, depending on your code base), but it works:
clang-tidy --checks=readability-implicit-bool-conversion your-file.cpp
yields
[...] warning: implicit conversion bool -> 'double' [readability-implicit-bool-conversion]
std::cout << foo(false) << std::endl; // here I want the warning
^~~~~
0.0
The real problem is the implicit conversion from bool to int (which is followed by a second conversion to double).
Booleans were added lately to the C++ language and never really considered semantically different from a number (just as there is no true character type).
As there is no narrowing of the type, finding a warning condition is difficult.
If you have the option of turning the bools to a custom class (maybe just temporarily), you can overload the conversion operators.
I'm trying to compile a program I got from the net. Trying to use in codeblocks but its showing errors. I don't understand what is going wrong. I've looked up in various forums but not much light is shed. Can anyone help soon? Thanks in advance
#include <functional>
#include <iostream>
int print_num(int i, int j) { return i + j; }
int main() {
std::function<int(int, int)> foo = print_num;
std::function<int(int, int)> bar;
try {
std::cout << foo(10, 20) << '\n';
std::cout << bar(10, 20) << '\n';
} catch (std::bad_function_call& e) {
std::cout << "ERROR: Bad function call\n";
}
return 0;
}
These are some of the errors other than 14 other errors saying declaration not done. I guess clearing these error would solve that problem.
main.cpp|10|error: 'function' is not a member of 'std'
main.cpp|10|error: expression list treated as compound expression in functional cast [-fpermissive]
main.cpp|10|error: expected primary-expression before 'int'
You need to compile with -std=c++11 to add in the C++11 features.
$ g++ -std=c++11 test.cxx && ./a.out
30
ERROR: Bad function call
vs:
$ g++ test.cxx && ./a.out
test.cxx: In function ‘int main()’:
test.cxx:10:3: error: ‘function’ is not a member of ‘std’
test.cxx:10:28: error: expression list treated as compound expression in functional cast [-fpermissive]
test.cxx:10:17: error: expected primary-expression before ‘int’
...
When I compile the code below with g++ 4.8.1 (64bit) in this way:
$ g++ -Wconversion -o main main.cpp
I get this result:
main.cpp: In function ‘int main()’:
main.cpp:12:20: warning: conversion to ‘int’ from ‘long unsigned int’ may alter its value [-Wconversion]
int i = sizeof(x)/sizeof(x[0]);
^
My expectation would be that the compiler should be able to evaluate the expression at compile time. If you make a similar program in plain c, gcc works like a charm.
Should this be considered a bug in g++ (e.g. clang++ does not have this problem)?
if you change the problematic line to something like:
char c = 0x10000000/0x1000000;
then the compiler does not complain. This suggest that some constant evaluation is done before warning generation.
main.cpp:
#include <iostream>
struct foo {
int a;
int b;
};
foo x[50];
int main()
{
int i = sizeof(x)/sizeof(x[0]);
std::cout << i << std::endl;
return 0;
}
int i = sizeof(x)/sizeof(x[0]);
//int <-- std::size_t <-- std::size_t / std::size_t
The type of the expression sizeof(x)/sizeof(x[0]) is std::size_t which on your machine is unsigned long int. So conversion from this type to int is data-loss, if the source is bigger in size than the target.
Though, I agree that in your case, there would not be actual data-loss if the compiler actually computes the value, but I guess it applies -Wconversion before the actual computation.
sizeof() returns you std::size_t not int! So cast it or declare i as std::size_t.
std::size_t i = sizeof(x)/sizeof(x[0]);
Why do I get the error
Expression Syntax
on the m[0]= line in the code below?
struct menu{
int code;
char name[30];
}m[5];
int main() {
clrscr();
m[0]={1,"MAGGI"}; //try to check whether this works or not and it didn't actually
<<endl;
cout<<m[0].code<<"\t"<<m[0].name;
getch();
return 0;
}
Succinctly — you can't do that in C++ with the struct menu as written with just default constructors.
In C99, you could use:
m[0] = (struct menu){ 1, "MAGGI" }; // C99 compound literal
Even in C++11, that (meaning 'using a compound literal') is not valid.
The unadorned use of endl; attempts to generate a function pointer, but the function is overloaded so it doesn't compile. You should add an << endl to the end of the output, though.
G++ allows C99-style compound literals
It is interesting that GCC (tested GCC 4.7.1 on Mac OS X 10.8.4) accepts the compound literal notation, even with stringent warnings, but this is a GCC/G++ extension over standard C++:
g++ -O3 -g -Wall -Wextra -c x91.cpp
Code:
#include <iostream>
using namespace std;
struct menu
{
int code;
char name[30];
} m[5];
int main()
{
m[0] = (struct menu){ 1, "MAGGI" };
cout << m[0].code << "\t" << m[0].name << endl;
return 0;
}
You have to provoke G++ fairly hard to get it to complain:
$ g++ -O3 -g -Wall -Wextra -std=c++98 -pedantic x91.cpp -o x91
x91.cpp: In function ‘int main()’:
x91.cpp:11:34: warning: ISO C++ forbids compound-literals [-pedantic]
$ g++ -O3 -g -Wall -Wextra -std=c++11 -pedantic x91.cpp -o x91
x91.cpp: In function ‘int main()’:
x91.cpp:11:34: warning: ISO C++ forbids compound-literals [-pedantic]
$
C++ 2011 and 'list initialization' or 'extended initializer lists'
I think section 8.5 Initializers in general and 8.5.4 List-initialization in particular mean that you can in fact write what you originally had, if your class (structure in the example) has the appropriate support.
Consider this minor variant on your original code:
#include <iostream>
#include <cstring>
using namespace std;
struct menu
{
int code;
char name[30];
menu(int c, const char *n) : code(c) { strncpy(name, n, sizeof(name)); name[sizeof(name)-1] = '\0'; }
menu() : code(0) { name[0] = '\0'; }
} m[5];
int main()
{
menu m0 = { 2, "MAGGI 2" };
m[0] = (struct menu){ 1, "MAGGI 1" };
m[1] = { 3, "MAGGI 3" };
cout << m[0].code << "\t" << m[0].name << endl;
cout << m0.code << "\t" << m0.name << endl;
cout << m[1].code << "\t" << m[1].name << endl;
return 0;
}
This code compiles OK under G++, subject to warnings about compound literals not being part of standard C++, when compiled as shown:
$ g++ -O3 -g -Wall -Wextra -std=c++11 -pedantic x91.cpp -o x91
x91.cpp: In function ‘int main()’:
x91.cpp:16:39: warning: ISO C++ forbids compound-literals [-pedantic]
$ ./x91
1 MAGGI 1
2 MAGGI 2
3 MAGGI 3
$
We can debate the wisdom of the use of strncpy() — that is tangential to the subject under discussion. The default constructor is needed to allow the array to be defined. The other constructor is necessary for the extended list initialization. Comment out the non-default constructor and you get scads of compilation messages:
$ g++ -O3 -g -Wall -Wextra -std=c++11 -pedantic x91.cpp -o x91
x91.cpp: In function ‘int main()’:
x91.cpp:15:29: error: could not convert ‘{2, "MAGGI 2"}’ from ‘<brace-enclosed initializer list>’ to ‘menu’
x91.cpp:16:39: warning: ISO C++ forbids compound-literals [-pedantic]
x91.cpp:16:39: error: no matching function for call to ‘menu::menu(<brace-enclosed initializer list>)’
x91.cpp:16:39: note: candidates are:
x91.cpp:10:5: note: menu::menu()
x91.cpp:10:5: note: candidate expects 0 arguments, 2 provided
x91.cpp:5:8: note: constexpr menu::menu(const menu&)
x91.cpp:5:8: note: candidate expects 1 argument, 2 provided
x91.cpp:5:8: note: constexpr menu::menu(menu&&)
x91.cpp:5:8: note: candidate expects 1 argument, 2 provided
x91.cpp:17:26: error: no match for ‘operator=’ in ‘m[1] = {3, "MAGGI 3"}’
x91.cpp:17:26: note: candidates are:
x91.cpp:5:8: note: menu& menu::operator=(const menu&)
x91.cpp:5:8: note: no known conversion for argument 1 from ‘<brace-enclosed initializer list>’ to ‘const menu&’
x91.cpp:5:8: note: menu& menu::operator=(menu&&)
x91.cpp:5:8: note: no known conversion for argument 1 from ‘<brace-enclosed initializer list>’ to ‘menu&&’
$
In C++98 mode (with both constructors present), you get a warning about using 'extended initializer lists' outside C++11 compliance mode:
$ g++ -O3 -g -Wall -Wextra -std=c++98 -pedantic x91.cpp -o x91
x91.cpp: In function ‘int main()’:
x91.cpp:15:29: error: in C++98 ‘m0’ must be initialized by constructor, not by ‘{...}’
x91.cpp:16:39: warning: ISO C++ forbids compound-literals [-pedantic]
x91.cpp:17:26: warning: extended initializer lists only available with -std=c++11 or -std=gnu++11 [enabled by default]
$
Declare constructors for the struct and use them. Also try using std::string over char[]. It is not possible to do as you have done. the constructor could be as
menu(int _code, string _name):code(_code), name(_name)
{} //changing name to string
with that, don't forget to declare a default constructor as well as you are creating an array of struct variables