# Preprocessor

This topic is 4866 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I want to create a macro which uses the preprocessor for something, for an example see this code:
#define FOO()\
#if defined(FOO_CALLED)\
#error Only call FOO once.\
#else\
#define FOO_CALLED\
#endif


When I call this it gives me the following errors:
g:\ab\texttest\texttest\main.cpp(14) : error C2121: '#' : invalid character : possibly the result of a macro expansion
g:\ab\texttest\texttest\main.cpp(14) : error C2059: syntax error : 'if'
g:\ab\texttest\texttest\main.cpp(14) : error C2121: '#' : invalid character : possibly the result of a macro expansion
g:\ab\texttest\texttest\main.cpp(14) : error C2121: '#' : invalid character : possibly the result of a macro expansion
g:\ab\texttest\texttest\main.cpp(14) : error C2121: '#' : invalid character : possibly the result of a macro expansion
g:\ab\texttest\texttest\main.cpp(14) : error C2121: '#' : invalid character : possibly the result of a macro expansion


Does anyone know how to do such a thing?

##### Share on other sites
Thanks.

I'm not sure I understood what the text said, it does mean that you can't use the preprocessor directives directly in the macro, but you could trick it into allowing it, by passing the directives through a parameter like this, right?:

//Remove WONT_COMPILE and the program should compile#define WONT_COMPILE() #define A#define WILL_COMPILE(x) (x)int main(){	WONT_COMPILE();	WILL_COMPILE(		#define A	);#ifndef A#	error A weren't defined in the macro.#endif}

The problem is that even though I remove both the macro call(WONT_COMPILE()) and the macro itself(#define WONT_COMPILE() ...) it won't compile. I have tried with MSVC 2003 .NET, MSVC 2005 .NET express and Dev-cpp, but none of them compiles it succesfully. I get the following errors:

g:\ab\texttest\texttest\main.cpp(9) : error C2121: '#' : invalid character : possibly the result of a macro expansiong:\ab\texttest\texttest\main.cpp(9) : error C2065: 'define' : undeclared identifierg:\ab\texttest\texttest\main.cpp(9) : error C2146: syntax error : missing ')' before identifier 'A'g:\ab\texttest\texttest\main.cpp(9) : error C2059: syntax error : ')'g:\ab\texttest\texttest\main.cpp(12) : fatal error C1189: #error :  A weren't defined in the macro.

With this program:

//Remove WONT_COMPILE and the program should compile#define WILL_COMPILE(x) (x)int main(){	WILL_COMPILE(		#define A	);#ifndef A#	error A weren't defined in the macro.#endif}

##### Share on other sites
Is this what you're looking for?

#define FOO()#ifdef FOO_CALLED#error Only call FOO once.#else#define FOO_CALLED#endif

##### Share on other sites
Quote:
 Original post by InsaneBoarder234Is this what you're looking for?*** Source Snippet Removed ***

Thanks for the reply, but no that aren't what I'm looking for. The FOO macro should expand to:
#if defined(FOO_CALLED)#error Only call FOO once.#else#define FOO_CALLED#endif

When called. For example this code:
#define FOO()#ifdef FOO_CALLED#error Only call FOO once.#else#define FOO_CALLED#endifFOO()FOO()int main(){}

Will result in this:

//The if was false, because FOO_CALLED weren't//defined before#define FOO_CALLED//The FOO() macro equals nothingint main(){}

But what I was looking for was something which resulted in this:

//Here are the first call to FOO()#define FOO_CALLED//Here are the second call to FOO()#error Only call FOO once.int main(){}

##### Share on other sites
If you explain why you want to do this someone may be able to suggest a (possibly better) alternative.

Enigma

##### Share on other sites
Quote:
 Original post by EnigmaIf you explain why you want to do this someone may be able to suggest a (possibly better) alternative.

Agreed. My philosophy on the preprocessor is that it has its uses, but should generally be avoided where possible - unless you have a good reason to use it.

##### Share on other sites
Quote:
 Original post by EnigmaIf you explain why you want to do this someone may be able to suggest a (possibly better) alternative.Enigma

On the frontpage there is a link to an article which shows a way to make a xml based logger. It mentions the __NAMESPACE__ keyword which are not a part of the C++ language.

So I wanted to implent the __NAMESPACE__ keyword in my project, the first solution I got was:

const std::string __NAMESPACE__ = "";#define NAMESPACE(Name)\ namespace Name\ {\ const std::string _TEMP_NAMESPACE_NAME__INTERNAL = __NAMESPACE__;\ const std::string __NAMESPACE__ = (_TEMP_NAMESPACE_NAME__INTERNAL + "::") + #Name;\ }\ namespace Name

But I quickly found an error with this approach, if you use the NAMESPACE macro more than once _TEMP_NAMESPACE_NAME__INTERNAL and __NAMESPACE__ will be defined multiple times.

If I could use the preprocessor directives inside a macro I could do something like this:

const std::string __NAMESPACE__ = "";#define ADD(a,b) (a##b)#define NAMESPACE(Name)\ namespace Name\ {\ #ifndef ADD(__NAMESPACE__,Name)\ const std::string _TEMP_NAMESPACE_NAME__INTERNAL = __NAMESPACE__;\ const std::string __NAMESPACE__ = (_TEMP_NAMESPACE_NAME__INTERNAL + "::") + #Name;\   #define ADD(__NAMESPACE__,Name)\ #endif\ }\ namespace Name

So I need a way to implent a __NAMESPACE__ variable.

EDIT: Just saw that my last example would not even work if the preprocessor directives could go inside macros because the ADD macro get __NAMESPACE__ as its first parameter, __NAMESPACE__ is a string, which aren't expected.

##### Share on other sites
As far as I know the C preprocessor doesn't allow preprocessor commands inside macros. I did find a solution that might work though:
#define CAT(A,B) CAT2(A,B)#define CAT2(A,B) A##Bconst std::string __NAMESPACE__ = "";#define NAMESPACE(Name)\   namespace CAT(Name,__LINE__) {\     const std::string _TEMP_NAMESPACE_NAME__INTERNAL = __NAMESPACE__;\     const std::string __NAMESPACE__ = (_TEMP_NAMESPACE_NAME__INTERNAL + "::") + #Name;\   }\   namespace Name{\     using namespace CAT(Name,__LINE__);\   }\   namespace CAT(Name,__LINE__)

EDIT: gdnet messed up \s

##### Share on other sites
twanvl: Thanks for the reply, but your code doesn't work imagine this:

#include "Namespace.h" // Include the namespace stuff discussed in this thread//// Some documentation//NAMESPACE(a){void Test();}

//Source.cpp
#include "Header.h"NAMESPACE(a){void Test(){std::cout << "Testing..." << std::endl;}}

The Header.h will then evaluate to something like this:
#include "Namespace.h" // Include the namespace stuff discussed in this thread//// Some documentation//namespace a6{    const std::string _TEMP_NAMESPACE_NAME__INTERNAL = __NAMESPACE__;\     const std::string __NAMESPACE__ = (_TEMP_NAMESPACE_NAME__INTERNAL + "::") + #Name;\ }namespace a{    using namespace a6;}namespace a6{    void Test();}

So the declaration will be in the a6 namespace and a will include the a6 namespace.

Then the source will evalute to this:
#include "Header.h" namespace a3{    const std::string _TEMP_NAMESPACE_NAME__INTERNAL = __NAMESPACE__;\     const std::string __NAMESPACE__ = (_TEMP_NAMESPACE_NAME__INTERNAL + "::") + #Name;\ }namespace a{    using namespace a3;}namespace a3{    void Test()    {        std::cout << "Testing..." << std::endl;    }}

The problem now is that the definition is in a3 while the declaration is in a6, so they are different functions and the compiler will only see the a3 and can therefore not see the definition.

Even though we'ld put them both in the header file. We would have the definition in a3::Test while the declaration is a6::Test and a uses both namespaces this result in that the compiler doesn't know wether to call a3::Test or a6::Test.

1. 1
2. 2
3. 3
4. 4
Rutin
17
5. 5

• 14
• 9
• 10
• 12
• 17
• ### Forum Statistics

• Total Topics
632909
• Total Posts
3009169
• ### Who's Online (See full list)

There are no registered users currently online

×