I have a project in which I want to use both grpc and ncurses and I stumbled across a strange error
I have a function
grpc::Status test(){
...
return grpc::Status::OK;
}
which works fine without ncurses, however if I add
#include <ncurses.h>
The whole thing breaks with this error
src/main.cc:32:26: error: expected unqualified-id before ‘(’ token
32 | return grpc::Status::OK;
| ^~
make: *** [makefile:34: obj/main.o] Error 1
As it turn out, ncurses also has
#undef OK
#define OK (0)
Is there a way to tackle this problem? Here are my ideas of what could work, but I don't know how to implement them.
namespace mangling
ifndefs
different compilation method
I am compiling my program with:
g++ -lncurses -lprotobuf -lgrpc++ -lgrpc++_reflection
Seems like you can just #undef it.
Related
I am trying to a C++ library and need (want) to use nested namespaces in order to increase readability of the code. However, I am running into a problem when trying to compile my code in the Windows Command Prompt with g++ main.c.
The code below is an example of what I will have -- a nested namespace and then some functions or classes:
namespace gpc::warning {
void raiseError() {
std::cout << "Error...\n";
exit(1);
}
}
The code below is an example for my main.c file:
#include <iostream>
#include "Warning/raise.hpp"
int main() {
std::cout << "Hello, World!" << std::endl;
gpc::warning::raiseError();
return 0;
}
When I run this simple probram in CLion, it compiles and runs perfectly, however when I run the code in the Windows 10 Command Prompt, I get the following error telling me something about the namespaces:
In file included from main.cpp:2:0:
Warning/raise.hpp:10:14: error: expected '{' before '::' token
namespace gpc::warning {
^
Warning/raise.hpp:10:16: error: 'warning' in namespace '::' does not name a type
namespace gpc::warning {
^
main.cpp: In function 'int gpc::main()':
main.cpp:9:10: error: 'gpc::warning' has not been declared
gpc::warning::raiseError();
^
main.cpp: At global scope:
main.cpp:12:1: error: expected '}' at end of input
}
^
I was wondering what I am doing wrong and how I can fix this problem.
Thanks!
Try updating your g++ version to 6.1.0 or higher.
The code doesn't compiles on g++ v5.5.0 even with -std=gnu++17 flag. You can check that here. (Reason: Nested namespaces weren't supported by the compiler then.)
The code shall compile with compiler defaults (without any flags) on g++ v6.1.0 or higher. You can check this here.
You can check your compiler version by running: g++ --version on cmd.
Pro Tip: Locate your CLion's compiler and if it is g++ then add that one to path. (No need of wasting internet data on updating the old g++ compiler!)
This is probably the weirdest thing I have seen in the last few years.
I have a project that builds perfectly well in two completely different machines (openSUSE Tumbleweed and ubuntu 14.04).
I started with a new machine using kubuntu 16.04 and this error started happening:
$ g++ -std=c++14 cout_qualif.cpp -lpng -o cout_qualif
In file included from cout_qualif.cpp:1:0:
debug_utils.h:19:19: error: invalid use of ‘::’
# define msg std::cout
Clang also points an error, but with a quite different message:
$ clang -std=c++14 cout_qualif.cpp -lpng -o cout_qualif
In file included from cout_qualif.cpp:3:
In file included from /usr/include/png++/png.hpp:34:
In file included from /usr/include/png.h:317:
/usr/include/zlib.h:94:19: error: non-friend class member 'cout' cannot have a qualified name
z_const char *msg; /* last error message, NULL if no error */
^~~
./debug_utils.h:19:19: note: expanded from macro 'msg'
# define msg std::cout
~~~~~^
1 error generated.
The simplest test code I've came across is:
#include <iostream>
#include "debug_utils.h"
#include <png++/png.hpp>
int main()
{
msg << "Start" << std::endl;
png::image< png::rgb_pixel > image("input.png");
image.write("output.png");
msg << "Finish" << std::endl;
return 0;
}
And "debug_utils.h":
#ifndef DEBUG_UTILS_H
#define DEBUG_UTILS_H
#include <iostream>
# define msg std::cout
#endif // DEBUG_UTILS_H
It turns out that "png.h" includes "zlib.h" and there is defined a struct:
typedef struct z_stream_s {
// ...
z_const char *msg; /* last error message, NULL if no error */
This msg member is what is triggering the error. If I move my #include "debug_utils.h" one line below, after #include <png++/png.hpp>, everything seems to work fine.
Now finally the question:
Why this machine cannot compile my code while two other can?
Additional info:
Kubuntu 16.04:
$ g++ --version
g++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
$ clang --version
clang version 3.8.0-2ubuntu4 (tags/RELEASE_380/final)
openSUSE Tumbleweed:
g++ is 7.1.1
Ubuntu 14.04:
Exact version not available at hand but I believe it is 4.9.x
To recap the cause of the problem
# define msg std::cout
in debug_utils.h substitutes std::cout for any instances of msg throughout the code after debug_utils.h is included. As msg is a common short identifier, particularly for a message buffer, an unintended substitution has always been a risk lurking in the code. The solution to this is obvious: Don't do that. Use a longer, less likely to be duplicated substitution or don't do it at all and replace the macro. Without seeing your usecase I'd probably replace the macro with a function that returns the correct stream and the compiler can easily inline.
The confusion and the question stems from why an error from the macro substitution only arises from a simple piece of test code when compiled on only one of three candidate PCs.
The answer is differences in the toolchain and support libraries. For one reason or another, on only one of these PCs a third-party header that uses the msg identifier is included by a third-party header included by the test program. The other two follow different inclusion paths to build the same program and avoid tripping over the unwanted substitution.
I have read other posts regarding this error but I have not been able to solve my problem. It could be something obvious with my code, but the code seems fine to me. The compiler log output is:
mingw32-make.exe -f "C:\Users\Michael\Desktop\Durham Courses\Summer 2015\OOP Object-Oriented Programming\Dev CPP Directory\Makefile.win" all
g++.exe cash.o main.o -o Lab3Functions.exe -L"C:/Program Files (x86)/Dev-Cpp/MinGW64/lib" -L"C:/Program Files (x86)/Dev-Cpp/MinGW64/x86_64-w64-mingw32/lib" -static-libgcc
main.o:main.cpp:(.text+0x0): multiple definition of `cash(double, int&, int&, int&, int&, int&, int&, int&)'
cash.o:cash.cpp:(.text+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
C:\Users\Michael\Desktop\Durham Courses\Summer 2015\OOP Object-Oriented Programming\Dev CPP Directory\Makefile.win:25: recipe for target 'Lab3Functions.exe' failed
mingw32-make.exe: *** [Lab3Functions.exe] Error 1
Compilation failed after 0.91 seconds with errors
Could it be this multiple definition bit toward the end? What I've done (as per my assignment) is created one file (cash.cpp) which contains the definition of cash function and then I've got:
#include "cash.cpp"
at the top of my main. Is that not correct?
I tried simulating your issue:
Here is my test.cpp with the main function:
#include <stdio.h>
#include "cash.cpp"
using namespace std;
int main()
{
printf("%d",cash());
return 0;
}
And here is cash.cpp:
int cash()
{
return 10;
}
And 10 is the output.
Your cash.cpp and the main file must be in the same directory. And ensure only one such file is in the same directory.
Also it could be related to C Drive privileges on Windows.
In that case a workaround can be found here: Dev C++ compilation error, permission denied.
Also, see this (Possible linker failure). Check that the forward declarations of the function are consistent with the definition.
I ended up creating a header file which contained the definitions for the functions in my main(). I used #ifndef to get around the multiple definitions problem.
My assignment required the use of a .cpp but I can't get it to work, so at least this compiles and runs. Thank you all for your help!
I am trying to use the Accelerate framework on a small C++ program. I'm not even using XCode, only a simple Makefile.
The compiler complains when I add the following line to my code:
#include <Accelerate/Accelerate.h>
The error is the following:
In file included from /System/Library/Frameworks/vecLib.framework/Headers/vecLib.h:41,
from /System/Library/Frameworks/Accelerate.framework/Headers/Accelerate.h:20,
from Diana.cpp:20:
/System/Library/Frameworks/vecLib.framework/Headers/vDSP.h:9008: error: expected identifier before numeric constant
/System/Library/Frameworks/vecLib.framework/Headers/vDSP.h:9008: error: expected `}' before numeric constant
/System/Library/Frameworks/vecLib.framework/Headers/vDSP.h:9008: error: expected unqualified-id before numeric constant
/System/Library/Frameworks/vecLib.framework/Headers/vDSP.h:9028: error: expected declaration before ‘}’ token
The compiler I'm using is i686-apple-darwin11-llvm-g++-4.2, which is a gcc 4.2.1, and the line that I use to compile (not to link) is:
i686-apple-darwin11-llvm-g++-4.2 -D__MACOSX_CORE__ -c -o Diana.o Diana.cpp
Should I add some additional flag(s) when compiling this? I tried adding the "-framework Accelerate", but it doesn't change anything, since this should only be included in the linkage process (am I right?).
I googled some of these error messages and I didn't find anything.
I would really appreciate any help. Thank you!
PS: My OS X version is Lion 10.7.5, and XCode is 4.4.1.
I figured it out: I checked what was on line 9008 of vDSP.h and the problem was that I was declaring an FFT_FORWARD constant before including the Accelerate.h.
Fixed!
I'm looking for an implementation of Hybrid Tree(not important), and find an "old" one here.
The author said they have tried this code on the SUN Sparc platform (running Solaris 2.6) and with gcc-2.8.1 compiler. And my environment is gcc version 4.4.3 (Ubuntu 10.10).
The problem is:
I run "make" with the makefile he provides, but it gives me lots of error message as follows:
g++ -c Node.C
g++ -c DataNode.C
In file included from DataNode.h:18,
from DataNode.C:17:
Query.h:9:20: error: vector.h: No such file or directory
Query.h:10:19: error: stack.h: No such file or directory
Query.h:13:22: error: function.h: No such file or directory
Query.h:14:22: error: iostream.h: No such file or directory
DataNode.C:283:8: warning: extra tokens at end of #endif directive
In file included from DataNode.h:18,
from DataNode.C:17:
Query.h:29: warning: ‘typedef’ was ignored in this declaration
Query.h:44: warning: ‘typedef’ was ignored in this declaration
Query.h:86: error: expected initializer before ‘<’ token
Query.h:118: error: ISO C++ forbids declaration of ‘PQ’ with no type
Query.h:118: error: expected ‘;’ before ‘*’ token
Query.h:122: error: ISO C++ forbids declaration of ‘PQ’ with no type
Query.h:122: error: expected ‘;’ before ‘*’ token
Query.h:126: error: ISO C++ forbids declaration of ‘PQ’ with no type
Query.h:126: error: expected ‘;’ before ‘*’ token
Query.h:135: error: expected initializer before ‘<’ token
DataNode.C: In member function ‘void DataNode::DisconnectBranch(int)’:
DataNode.C:80: error: ‘memmove’ was not declared in this scope
make: *** [DataNode.o] Error 1
I know I need to modify the souce code so as to agree with the morden compiler, such as change vector.h to vector. But I find it's just endless.
So my question is: is there any convienent method to run this program, no matter automatically converting this code to "modern-style" or using a standalone "old-style" compiler ?
Any suggestions?
===Update:===
Thank you all, I installed gcc2.8.1 in a different dir using --prefix=/usr/local/gcc-2.8.1 and modify the "makefile" to use this old-version gcc(/usr/local/gcc-2.8.1/bin/gcc). But when I run "make", it still gives me errors of not finding the headers:
/usr/local/gcc-2.8.1/bin/gcc -c DataNode.C
In file included from DataNode.h:18,
from DataNode.C:17:
Query.h:9: vector.h: No such file or directory
Query.h:10: stack.h: No such file or directory
Query.h:11: deque: No such file or directory
Query.h:12: algorithm: No such file or directory
Query.h:13: function.h: No such file or directory
Query.h:14: iostream.h: No such file or directory
make: *** [DataNode.o] Error 1
Then I tried to find these heads in /usr/local/gcc-2.8.1 using find /usr/local/gcc-2.8.1 -name "*vector*", but got nothing.
So where are these heads for the old-version gcc?
You can make a vertor.h yourself which includes vector. This way you can fix the incompatibilities noninvasively.
Edit:
You may also need to add a
using namespace std;
in the header file(s). This is
generally a bad idea but this is one situation where i'd do it anyway.
Once you get it working i would reccomend rewriting it to use the new style header files and namespaces.
Debian Lenny (oldstable) has gcc 3.4. This might have a better backward compatibility. Try to make compatibility headers for the rest of the issues and include them via an extra -I directory, e.g. a vector.h header file that includes vector.
Do yourself the favor and try not to touch the old code. It is easy to break legacy code in unforeseen ways.
You could try running the program on QEMU which supports Solaris 2.6. The only problem might be hunting for the install disc/image. Also, there are people that sells old Solaris boxes on eBay for cheap, you might be able to grab one.
GCC provides download for very old versions, you might be able to get better chance if you try older version of the compiler.
gcc has -fpermissive option: try it and see whether at least some errors disappear. Also: try making a single header file that will include all requisite headers with using directives. For example, make stdinc.h containing:
#include <vector>
#include <iostream>
#include <stack>
...
using std::vector;
using std::fstream;
...
Replace all mentions of legacy C++ header files with a single include of stdinc.h. Old C++ didn't have namespaces, so even if you replace individual directives with just using namespace std;, clashes are unlikely.
If the only thing is
#include <vector.h>
to
#include <vector>
using namespace std;
Why not try sed?
grep for all includes to see if there are other includes than the c++ headers. If not your lucky.
Another thing that is more tricky is that there is old code that relies on accessing data through iterators in a non-standard way. I saw that in a Doom map editor for linux. Then you may need to do manual stuff.