I am currently going through Bjarne Stroustrup's "The C++ Programming Language (4th Edition)" and am trying to understand whether is the following a syntax error or was it the way I compiled it.
According to the following code snippet (extracted from the book), my constructor should look like this:
class Vector {
public:
Vector(int s): elem{new double[s]}, sz{s} {} // Construct a Vector
...
private:
double* elem; // Pointer to the elements
int sz; // The number of elements
};
But, I am unable to compile it unless I change the following as per the suggestion of the error message:
Vector(int s): elem(new double[s]), sz(s) {}
Note: I compiled my C++ codes using the following command through the Mac Terminal:
g++ -ansi -pedantic -Wall Test.cpp -o Test.o
Thank you in advance.
Probably, all you need to do is to compile it for C++ 11:
g++ -std=c++11 -ansi -pedantic -Wall Test.cpp -o Test.o
As #molbdnilo pointed out in a comment, remove -ansi from the command, because this is a synonym for std=c89 or std=c++98.
g++ -std=c++11 -pedantic -Wall Test.cpp -o Test.o
Related
For this struct and function:
typedef struct data_s
{
int i1;
int i2;
} data_t;
void print_data_passed_by_ptr(const data_t *data)
{
printf(" i1 = %i\n"
" i2 = %i\n\n",
data->i1,
data->i2);
}
this works fine in C:
// Print R-value struct passed by ptr
print_data_passed_by_ptr(&(data_t){
.i1 = 7,
.i2 = 8,
});
My C build command is:
gcc -Wall -Wextra -Werror -O3 -std=c17 \
struct_pass_R_values_by_cpp_reference_and_ptr.c -o bin/a && bin/a
But, in C++ it fails with
error: taking address of temporary [-fpermissive]
My C++ build command is:
g++ -Wall -Wextra -Werror -O3 -std=c++17 \
struct_pass_R_values_by_cpp_reference_and_ptr.c -o bin/a && bin/a
So, I added -fpermissive to my C++ build command:
g++ -Wall -Wextra -Werror -O3 -std=c++17 -fpermissive \
struct_pass_R_values_by_cpp_reference_and_ptr.c -o bin/a && bin/a
and now the C++ build fails with this:
error: taking address of temporary [-Werror=permissive]
I tried turning off -Werror=permissive with -Wno-error=permissive (see here for that GCC documentation: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html, and search the page for -Wno-error=), but that's not a valid option. New build cmd I attempted:
g++ -Wall -Wextra -Werror -O3 -std=c++17 -fpermissive -Wno-error=permissive \
struct_pass_R_values_by_cpp_reference_and_ptr.c -o bin/a && bin/a
...fails with:
cc1plus: error: -Werror=permissive: no option -Wpermissive
So, how do I solve this to force this C code to build in C++? Either suppressing the warning/error, OR providing some modification to the code other than the one shown just below are acceptable answers. I want the code to compile as C also, not just C++, in the end.
I know I can use "const reference" in C++ instead of ptr, like this, and that's great and all and it might answer somebody else's question, but that's not my question:
void print_data_passed_by_cpp_reference(const data_t& data)
{
printf(" i1 = %i\n"
" i2 = %i\n\n",
data.i1,
data.i2);
}
// Print R-value struct passed by C++ reference
print_data_passed_by_cpp_reference({
.i1 = 9,
.i2 = 10,
});
I also know I can remove -Werror and keep -fpermissive to make it build, with warnings, like this:
eRCaGuy_hello_world/cpp$ g++ -Wall -Wextra -O3 -std=c++17 -fpermissive \
struct_pass_R_values_by_cpp_reference_and_ptr.c -o bin/a && bin/a
struct_pass_R_values_by_cpp_reference_and_ptr.c: In function ‘int main()’:
struct_pass_R_values_by_cpp_reference_and_ptr.c:87:5: warning: taking address of temporary [-fpermissive]
});
^
Hello world.
i1 = 7
i2 = 8
i1 = 9
i2 = 10
...but I'd really like to keep -Werror on and make that warning go away.
How to automatically pass an R-value parameter into a function as a const ptr for C and as a const reference for C++
(emphasis added to my original quote)
So, how do I solve this to force this C code to build in C++? Either suppressing the warning/error, OR providing some modification to the code other than the one shown just below are acceptable answers. I want the code to compile as C also, not just C++, in the end.
This works! It is one approach. If there are ways to disable the warning/error in gcc via command-line options I'd still like to know those though.
This is pretty clever I think. It passes the R-value by const ptr for C and by const reference for C++ by using two separate definitions for the print_data() function and the DATA_T macro, depending on the language.
#ifndef __cplusplus
// For C
void print_data(const data_t *data)
{
printf(" i1 = %i\n"
" i2 = %i\n\n",
data->i1,
data->i2);
}
#else
// For C++
void print_data(const data_t& data)
{
printf(" i1 = %i\n"
" i2 = %i\n\n",
data.i1,
data.i2);
}
#endif
#ifndef __cplusplus
// For C
#define DATA_T &(data_t)
#else
// For C++
#define DATA_T // leave empty
#endif
Usage:
// Print R-value struct passed by C++ reference, OR by C ptr, depending on
// whether this code is compiled as C or C++
print_data(DATA_T{
.i1 = 9,
.i2 = 10,
});
Build commands:
# For C
gcc -Wall -Wextra -Werror -O3 -std=c17 \
struct_pass_R_values_by_cpp_reference_and_ptr.c -o bin/a && bin/a
# For C++
g++ -Wall -Wextra -Werror -O3 -std=c++17 \
struct_pass_R_values_by_cpp_reference_and_ptr.c -o bin/a && bin/a
I got the following warning when compiling a C++ file :
variables.cpp:10:8: warning: extended initializer lists only available with -std=c++11 or -std=gnu++11
int c{2} ;
This is the file :
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std ;
int main()
{
int a = 0 ;
int b(1) ;
int c{2} ;
string myString = "I am a string !" ;
cout << a+b+c << endl ;
cout << myString << endl ;
return EXIT_SUCCESS ;
}
And this is the command line :
g++ -std=c++0x -Wall -Wextra -Winit-self -Wold-style-cast -Woverloaded-virtual -Wuninitialized -Wmissing-declarations -Winit-self -ansi -pedantic variables.cpp -o variables
I am using g++ 7.4.0 on Ubuntu 18.04.1
I do not want to ignore the warning but to solve it,
Thank you
PS : I tried to change -std=c++0x to -std=c++11 but it did not change anything
Remove -ansi in your command, which is equivalent to -std=c++98 and would overwrite your previous flag -std=c++11. According to C-Dialect-Options,
In C mode, this is equivalent to -std=c90. In C++ mode, it is equivalent to -std=c++98.
Replace -std=c++0x with -std=c++11.
Note that if your compiler supports it, it is recommended to use the lastest c++ standard which is -std=c++17. Using newer c++ standard usually makes your code shorter, more readable and more performant.
You have 2 problem in compilation command line:
The first one is the -ansi in compilation command that implicitly set the standard to the c++98. In you case the -ansi option generate conflict with -std=c++11.
The second one is the -std=c++0x, you have to replace it with -std=c++11.
Since the definition of template must be put in header file, so I don't like it if the template class is big. so I want to make a normal class with some templated methods. Putting the defintion of templated method into header file, for others, put them into c++ source files. So here is what I am thinking.
// lambda.h
#include <iostream>
class X {
public:
std::function<bool(int)> filter;
template <class F>
void setFilter(F fn) {
filter = fn;
}
void big_function(int x);
};
// cat lambda.cpp
#include <iostream>
#include "lambda.h"
void X::big_function(int x) {
if (filter(x)) std::cout << x << std::endl;
}
// main2.cpp
#include <stdlib.h>
#include "lambda.h"
class Filter {
public:
bool operator()(int x) { return true; }
};
int main() {
X x;
x.setFilter(Filter());
x.big_function(3);
return 0;
}
// cat 2.sh
g++ -c lambda.cpp -ggdb
g++ -c main2.cpp -ggdb -std=c++11
g++ -o main2 main2.o lambda.o -ggdb
this program can compile, but got segment fault during executing (x.big_function(3));
#update
Q1: is my thinking is reasonable? is there any obvious error in my code?
Answer: Yes, it is reasonable, and no obvious error. Thanks to the first 4 comments, I did more test and works.
Q2: actually if I compile with -std=c++11, I will got segment fault. but no segment fault if I don't use std=c++11. ( I tried c++11 yesterday because I used lambda expression rather than function object for "Filter" at beginning). And it my real case, I can't discard c++11 features.
Answer: shame about my fault. fixed the issue by adding -std=c++11 for every compile unit.
zhifan$ sh -x 2.sh
+ g++ -c lambda.cpp -ggdb
+ g++ -c main2.cpp -ggdb
+ g++ -o main2 main2.o lambda.o -ggdb
zhifan$ ./main2
3
zhifan$ vim 2.sh
hifan$ sh -x 2.sh
+ g++ -c lambda.cpp -ggdb **-std=c++11**
+ g++ -c main2.cpp -ggdb -std=c++11
+ g++ -o main2 main2.o lambda.o -ggdb
zhifan$ ./main2
Segmentation fault: 11
zhifan$ g++ -v
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.4.0
Thread model: posix
I have an unfortunate problem. My GCC 4.6.3 compiler refuses to compile my move constructor.
Exchanging line 6 in the example with "MemoryBlock(const MemoryBlock & other)" would make it compile, but not using the below move constructor declaration. Seems like the compiler does not know C+11, even though it should using 4.6.3. Right?
#include <cstddef>
class MemoryBlock
{
public:
MemoryBlock(MemoryBlock && other) //<----------- RAD 6.
{
}
private:
size_t _length; // The length of the resource.
int* _data; // The resource.
};
int main() {
}
Compiler output:
prog.cpp:6:28: error: expected ‘,’ or ‘...’ before ‘&&’ token
prog.cpp:6:36: error: invalid constructor; you probably meant ‘MemoryBlock (const MemoryBlock&)’
make: * [slask] Error 1
GCC version:
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 (Kör från labbsal i skolan)
makefile:
%.out: %.cpp
g++ -g -W -Wall -std=c++0x $*.cpp -o $*.out;
Try -std=c++11 instead of -std=c++0x. While your compiler knows the usage, the -std=c++0x "turns off" those new rules.
Have a look at this piece of C++ code:
class Foo
{
int a;
public: Foo(int b): a(a) {}
};
Obviously, the developer meant to initialize a with b rather than a itself, and this is a pretty hard to spot error.
Clang++ will warn about this possible mistake while GCC won't, even with additional warnings enabled:
$ clang++ -c init.cpp
init.cpp:5:27: warning: field is uninitialized when used here [-Wuninitialized]
public: Foo(int b): a(a) {}
^
$ g++ -Wall -Wuninitialized -Winit-self -c init.cpp
$
Is there any chance of enabling the same output for g++?
Use a newer gcc :-) Seems to work fine for me:
stieber#gatekeeper:~$ g++ -Wall -Wuninitialized -Winit-self -c Test.cpp
Test.cpp: In constructor ‘Foo::Foo(int)’:
Test.cpp:5:9: warning: ‘Foo::a’ is initialized with itself [-Wuninitialized]
stieber#gatekeeper:~$ gcc --version
gcc (Debian 4.7.1-2) 4.7.1