Jump to content
  • Advertisement
Sign in to follow this  
CTar

Preprocessor

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

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
Share on other sites
Advertisement
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 expansion
g:\ab\texttest\texttest\main.cpp(9) : error C2065: 'define' : undeclared identifier
g:\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 this post


Link to post
Share on other sites
Quote:
Original post by InsaneBoarder234
Is 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
#endif

FOO()
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 nothing

int 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 this post


Link to post
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 this post


Link to post
Share on other sites
Quote:
Original post by Enigma
If 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 this post


Link to post
Share on other sites
Quote:
Original post by Enigma
If 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 this post


Link to post
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##B

const 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 this post


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

//Header.h

#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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!