Here is what I am thinking.
#define prefix_1 1
#define prefix_2 2
#define prefix_3 3
And I want to define a macro using the prefixes above — like macro macro_prefix_1 macro_prefix_2 — and I expect them to turn into macro_1 macro_2, etc. Just like the code below
#define macro_##prefix_1 I_am_macro_1
#define macro_##prefix_2 I_am_macro_2
Is this possible?
Unfortunately, what you are trying to do is impossible. The (##) directive is impossible to use within a macro declaration. It is only possible to use it within the definition as such.
#define glue(a,b) a ## b
glue(c,out) << "test";
Example borrowed from cplusplus.com
Below, I have written an example of what you want to do.
#include <stdio.h>
#define prefix_1 1
#define prefix_2 2
#define prefix_3 3
#define macro_##prefix_1 "macro_1"
#define macro_##prefix_2 "macro_2"
#define macro_##prefix_3 "macro_3"
int main(){
printf("%s\n%s\n%s\n", macro_prefix_1, macro_prefix_2, macro_prefix_3);
return 0;
}
When you try to compile the above code you will get this build log.
||=== Build: Debug in file_test (compiler: GNU GCC Compiler) ===|
main.cpp|7|warning: missing whitespace after the macro name [enabled by default]|
main.cpp|7|error: '##' cannot appear at either end of a macro expansion|
main.cpp|8|warning: missing whitespace after the macro name [enabled by default]|
main.cpp|8|error: '##' cannot appear at either end of a macro expansion|
main.cpp|9|warning: missing whitespace after the macro name [enabled by default]|
main.cpp|9|error: '##' cannot appear at either end of a macro expansion|
main.cpp||In function 'int main()':|
main.cpp|13|error: 'macro_prefix_1' was not declared in this scope|
main.cpp|13|error: 'macro_prefix_2' was not declared in this scope|
main.cpp|13|error: 'macro_prefix_3' was not declared in this scope|
||=== Build failed: 6 error(s), 3 warning(s) (0 minute(s), 0 second(s)) ===|
So if you want to be able to have macro's you will just have to add the prefix normally. Luckily you were basically already doing this, but adding "##". Hope this helped.
Related
I have a command line argument that defines the type to use for a Vector3 class. It is defined in the SConstruct file as follows:
EnumVariable('vector3_type', 'The type to use for Vector3\'s xyz coordinates', 'float', allowed_values=['float', 'double', 'long_double'], ignorecase=2)
This variable is added to the environment here:
if env['vector3_type'] != 'long_double':
env.Append(CPPDEFINES = ["BIGROCK_VEC3_TYPE %s" % env['vector3_type']])
else:
env.Append(CPPDEFINES = ["BIGROCK_VEC3_TYPE long double"])
This works fine on Windows 10, but when I try to compile on OSX, I get the following error:
In file included from src/octree.cpp:1:
In file included from src/octree.h:5:
src/vector3.h:15:9: error: expected member name or ';' after declaration specifiers
BIGROCK_VEC3_TYPE x, y, z;
^~~~~~~~~~~~~~~~~
<command line>:1:33: note: expanded from here
#define BIGROCK_VEC3_TYPE float 1
~~~~~ ^
Either scons or g++ is adding an extra '1' to the end of my macro, causing the rest of my code to break.
When I print env['vector3_type'] in scons, it doesn't have a 1 attached. I have no idea where this 1 is being added.
This makes me feel a bit foolish. Scons assumes that a lone string within CPPDEFINES is a flag name, and will append 1 to it for #ifdef and #ifndef directives. The proper way to pass this #define is:
if env['vector3_type'] != 'long_double':
env.Append(CPPDEFINES = [("BIGROCK_VEC3_TYPE", env['vector3_type'])])
else:
env.Append(CPPDEFINES = [("BIGROCK_VEC3_TYPE", "long double")])
I am new to vein and omnet++. I followed this tutorial http://veins.car2x.org/tutorial/ everything works up to step 3, for some reason veins 4.7 doesn't build in omnet++ 5 (IDE) and generates the following errors.
veins/modules/utility/TimerManager.cc
In file included from veins/modules/utility/TimerManager.cc:20:
.\veins/modules/utility/TimerManager.h:137:26: error: expected identifier
enum class StartMode { RELATIVE, ABSOLUTE, IMMEDIATE };
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1434:18: note: expanded from macro 'RELATIVE'
#define RELATIVE 2
^
In file included from veins/modules/utility/TimerManager.cc:20:
.\veins/modules/utility/TimerManager.h:137:36: error: expected identifier
enum class StartMode { RELATIVE, ABSOLUTE, IMMEDIATE };
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1433:18: note: expanded from macro 'ABSOLUTE'
#define ABSOLUTE 1
^
In file included from veins/modules/utility/TimerManager.cc:20:
.\veins/modules/utility/TimerManager.h:138:24: error: expected identifier
enum class EndMode { RELATIVE, ABSOLUTE, REPITITION, OPEN };
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1434:18: note: expanded from macro 'RELATIVE'
#define RELATIVE 2
^
In file included from veins/modules/utility/TimerManager.cc:20:
.\veins/modules/utility/TimerManager.h:138:34: error: expected identifier
enum class EndMode { RELATIVE, ABSOLUTE, REPITITION, OPEN };
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1433:18: note: expanded from macro 'ABSOLUTE'
#define ABSOLUTE 1
^
veins/modules/utility/TimerManager.cc:42:28: error: expected unqualified-id
start_mode_ = StartMode::RELATIVE;
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1434:18: note: expanded from macro 'RELATIVE'
#define RELATIVE 2
^
veins/modules/utility/TimerManager.cc:48:28: error: expected unqualified-id
start_mode_ = StartMode::ABSOLUTE;
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1433:18: note: expanded from macro 'ABSOLUTE'
#define ABSOLUTE 1
^
veins/modules/utility/TimerManager.cc:54:24: error: expected unqualified-id
end_mode_ = EndMode::RELATIVE;
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1434:18: note: expanded from macro 'RELATIVE'
#define RELATIVE 2
^
veins/modules/utility/TimerManager.cc:60:24: error: expected unqualified-id
end_mode_ = EndMode::ABSOLUTE;
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1433:18: note: expanded from macro 'ABSOLUTE'
#define ABSOLUTE 1
^
veins/modules/utility/TimerManager.cc:86:19: error: expected unqualified-id
case StartMode::RELATIVE:
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1434:18: note: expanded from macro 'RELATIVE'
#define RELATIVE 2
^
veins/modules/utility/TimerManager.cc:88:30: error: expected unqualified-id
start_mode_ = StartMode::ABSOLUTE;
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1433:18: note: expanded from macro 'ABSOLUTE'
#define ABSOLUTE 1
^
veins/modules/utility/TimerManager.cc:90:19: error: expected unqualified-id
case StartMode::ABSOLUTE:
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1433:18: note: expanded from macro 'ABSOLUTE'
#define ABSOLUTE 1
^
veins/modules/utility/TimerManager.cc:98:17: error: expected unqualified-id
case EndMode::RELATIVE:
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1434:18: note: expanded from macro 'RELATIVE'
#define RELATIVE 2
^
veins/modules/utility/TimerManager.cc:100:26: error: expected unqualified-id
end_mode_ = EndMode::ABSOLUTE;
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1433:18: note: expanded from macro 'ABSOLUTE'
#define ABSOLUTE 1
^
veins/modules/utility/TimerManager.cc:102:17: error: expected unqualified-id
case EndMode::ABSOLUTE:
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1433:18: note: expanded from macro 'ABSOLUTE'
#define ABSOLUTE 1
^
veins/modules/utility/TimerManager.cc:106:26: error: expected unqualified-id
end_mode_ = EndMode::ABSOLUTE;
^
C:\Users\Abu\src\omnetpp-5.3\tools\win64\mingw64\x86_64-w64-mingw32\include\wingdi.h:1433:18: note: expanded from macro 'ABSOLUTE'
#define ABSOLUTE 1
^
15 errors generated.
make[1]: *** [Makefile:205: ../out/clang-debug/src/veins/modules/utility/TimerManager.o] Error 1
make[1]: Leaving directory '/c/Users/Abu/src/veins-4.7/src'
make: *** [Makefile:12: all] Error 2
I am also using sumo_win64_0.32.0. I am not sure what causes these errors.
Any help is greatly appreciated.
The issue has been fixed in this pull request and a new minor revision of Veins (i.e. Veins 4.7.1) has been released. Please download the new version to get the fix and also some additional improvements.
I just encountered that error as well and here is what happens:
The compiler cannot resolve the enum class definitions in TimerManager.h as there is a name ambiguity with the macros RELATIVE and ABSOLUTE within wingdi.h
enum class StartMode { RELATIVE, ABSOLUTE, IMMEDIATE };
enum class EndMode { RELATIVE, ABSOLUTE, REPITITION, OPEN };
Quick fix is to rename the occurrences in TimerManager.h and TimerManager.cc to something else. E.g. Replace all occurrences of RELATIVE with RELATIVEINS and ABSOLUTE with ABSOLUTEVEINS etc... (or whatever you like). Worked fine for me with 4.7 and OMNet++ 5.2.1.
A patch is required to make Veins 4.7 compile with OMNeT++ 5.3 for Windows. The cleanest way may be something like on https://pastebin.com/ymzqMpEF
- enum class StartMode { RELATIVE, ABSOLUTE, IMMEDIATE }
+ enum class StartMode { relative, absolute, immediate }
that is, renaming the all-uppercase enum class constants to lower case ones (something recommended by many coding styles as well).
i have in my legacy code this
#define max(x, y) (x > y ? x : y)
#define min(x, y) (x < y ? x : y)
that bean used allot in the application , now i try to compile it in freeBSD
and i keep getting :
/usr/include/c++/4.2/bits/istream.tcc:123:35: error: macro "min" requires 2 arguments, but only 1 given
/usr/include/c++/4.2/bits/istream.tcc:124:45: error: macro "max" requires 2 arguments, but only 1 given
/usr/include/c++/4.2/bits/istream.tcc:143:33: error: macro "min" requires 2 arguments, but only 1 given
/usr/include/c++/4.2/bits/istream.tcc:144:43: error: macro "max" requires 2 arguments, but only 1 given
/usr/include/c++/4.2/bits/istream.tcc:438:48: error: macro "max" requires 2 arguments, but only 1 given
/usr/include/c++/4.2/bits/istream.tcc:441:53: error: macro "min" requires 2 arguments, but only 1 given
/usr/include/c++/4.2/bits/istream.tcc:449:47: error: macro "max" requires 2 arguments, but only 1 given
/usr/include/c++/4.2/bits/istream.tcc:489:48: error: macro "max" requires 2 arguments, but only 1 given
/usr/include/c++/4.2/bits/istream.tcc:493:53: error: macro "min" requires 2 arguments, but only 1 given
/usr/include/c++/4.2/bits/istream.tcc:501:47: error: macro "max" requires 2 arguments, but only 1 given
/usr/include/c++/4.2/bits/istream.tcc:507:53: error: macro "max" requires 2 arguments, but only 1 given
/usr/include/c++/4.2/bits/istream.tcc:806:43: error: macro "max" requires 2 arguments, but only 1 given
i guess its the name of the methods in the code ( the macros ) .
now changing the name its to much work.
how can i keep using it but avoiding the compiler to mixup ?
What was the reason to define those macros in the first place? It's C++, no need for any macros, especially not those that are already given as functions to you by the standard (It always bothers me when including <windows.h> and getting complaints about their stupid min and max macros).
That being said, a quick and dirty solution might be to substitute your macro definitions with
#include <algorithm>
using std::min;
using std::max;
Though, this still pollutes the global namespace those are now proper function names that can be hidden by any local variables or any other functions or methods and are not just replaced everywhere by a stupid text-substituting preprocessor.
Other than that consider including any system include files before those macros (or usings).
I have a strange multiple definitions error in my project.
I'm using the #ifndef preprocessor command to avoid including the same file multiple times. I cleared all other code. Here are my simplified files:
1 - main.cpp
#include "IP.hpp"
int main()
{
return 0;
}
2 - IP.cpp
#include "IP.hpp"
//some codes!
3 - IP.hpp
#ifndef IP_HPP_INCLUDED
#define IP_HPP_INCLUDED
unsigned char LUTColor[2];
#endif // IP_HPP_INCLUDED
Using codeblocks & gnu gcc in win7, it says:
obj\Debug\main.o:C:\Users\aaa\Documents\prg\ct3\main.cpp|4|first defined here|
||=== Build finished: 1 errors, 0 warnings ===|
Before I deleted all of the other code, the error was:
||=== edgetest, Debug ===|
obj\Debug\IP.o||In function `Z9getHSVLUTPA256_A256_12colorSpace3b':|
c:\program files\codeblocks\mingw\bin..\lib\gcc\mingw32\4.4.1\include\c++\exception|62|multiple definition of `LUTColor'|
obj\Debug\main.o:C:\Users\aaa\Documents\prg\edgetest\main.cpp|31|first defined here|
||=== Build finished: 2 errors, 0 warnings ===|
And 'LUTColor' is in IP.hpp !
What's wrong?
The problem is in the header - you need:
#ifndef IP_HPP_INCLUDED
#define IP_HPP_INCLUDED
extern unsigned char LUTColor[2]; // Declare the variable
#endif // IP_HPP_INCLUDED
Do not define variables in headers!
You also need to nominate a source file to define LUTColor (IP.cpp is the obvious place).
See also: What are extern variables in C, most of which applies to C++ as well as C.
In C++ is there a mechanism to allow non terminated macros to be expressed?
This is a contrived example:
#define MACRO(x, y) x + y
#define MACROC1(x) MACRO(x,
#define MACROC2(y) y)
//...expecting 3
int foo = MACROC1(1) MACROC2(2);
I receive the error improperly terminated macro invocation from MSVC.
When I run cl -E file.cpp I see that the code below has been generated:
int c = 1 + 1 + 2);
In visual studio compilation fails with errors:
error C2059: syntax error : ')'
IntelliSense: improperly terminated macro invocation
I don't think this is possible. The C precompiler expands macros depth-first, so the MACROC1 will be full expanded before the MACROC2 is even considered. Then, it will find the MACRO with and incomplete argument list and throws an error.
Generally speaking, you should avoid defining macros that build other macro calls. Compilers tend not to agree in what those mean.
Your code would translate to :
int foo = MACRO(1, 2;
Which is wrong - it is an incomplete (improperly terminated) invocation of macro MACRO.