Is it possible to treat macro's arguments as regular expressions? - c++

Suppose I have a C++ macro CATCH to replace the catch statement and that macro receive as parameter a variable-declaration regular expression, like <type_name> [*] <var_name> or something like that. Is there a way to recognize those "fields" and use them in the macro definition?
For instance:
#define CATCH(var_declaration) <var_type> <var_name> = (<var_type>) exception_object;
Would work just like:
#define CATCH(var_type, var_name) var_type var_name = (var_type) exception_object;
As questioned, I'm using g++.

You can't do it with just macros, but you can be clever with some helper code.
template<typename ExceptionObjectType>
struct ExceptionObjectWrapper {
ExceptionObjectType& m_unwrapped;
ExceptionObjectWrapper(ExceptionObjectType& unwrapped)
: m_unwrapped(unwrapped) {}
template<typename CastType>
operator CastType() { return (CastType)m_wrapped; }
};
template<typename T>
ExceptionObjectWrapper<T> make_execption_obj_wrapper(T& eobj) {
return ExceptionObjectWrapper<T>(eobj);
}
#define CATCH(var_decl) var_decl = make_exception_obj_wrapper(exception_object);
With these definitions,
CATCH(Foo ex);
should work. I will admit to laziness in not testing this (in my defence, I don't have your exception object test with). If exception_object can only be one type, you can get rid of the ExceptionObjectType template parameter. Further more, if you can define the cast operators on the exception_object itself you can remove the wrappers altogether. I'm guessing exception_object is actually a void* or something though and your casting pointers.

What compiler are you using? I've never seen this done in the gcc preprocessor, but I can't say for sure that no preprocessor out there can implement this functionality.
What you could do however is run your script through something like sed to do your prepreprocessing so to speak before the preprocessor kicks in.

Hmmm... I'm just guessing, but why don't you try something like this : :)
#define CATCH(varType,varName) catch(varType& varName) { /* some code here */ }

Related

C++ Macro definition including dot?

I have some C++ code that I can't change, only by changing header files. I have the code and can compile it.
The issue is that I have a function pointer defined something like this (function pointer is kind of irrelevant to what I want to do):
foo.bar();
I would like change that with a macro or something to:
#define foo.bar() FunCall()
The issue as I understand is that it is not possible to use dots in a macro, is there any other way?
Edit:
A bit more info. The code I get is intended to run a single instance, however I'm wrapping the code to run multiple instances in a class. That gives some headaches I'm trying to over come.
What I'm trying is either to use a macro and some inline functions or a complete third way:
void function()
{
foo.bar();
}
I need some code that could make above equivalent to:
void class::function()
{
EventFuncTypedef f = foo.bar;
(this->*f)();
}
Or
void class::function()
{
class::FunCall();
}
The code above all work the issue is to try get option 1 or 2 executed by the original code.
with a macro and an helper:
struct FunCaller {
static auto bar() {FunCall();}
};
#define foo FunCaller{}

Is it possible to use a macro to create typedefs?

How can I create a typedef using a macro (#define)?
I am, for various reasons, trying to use a macro to do typedef'ing in C. Something along the lines of templates for C++.
As an example, I would expect the preprocessor to expand the #define and typedef a struct whose "content" member is of type char:
#define DEFINE_FOO_TYPE(content_type__, content_type_name__) \
typedef struct { \
content_type__ content; \
} content_type_name__
DEFINE_FOO_TYPE(char, foo_t);
foo_t foo_var;
foo_var.content = 'g';
Apparently that is not the case. Is it possible to do these sort of things in C at all, or is the only way a C++ template?
To preempt questions along the lines of "why don't you just use a C++ template?". The answer is that I'm trying to do it in C because it's fun.
Try this:
#define DEFINE_FOO_TYPE(content_type__, content_type_name__) \
typedef struct { \
content_type__ content; \
} content_type_name__
DEFINE_FOO_TYPE(char, foo_t);
int main() {
foo_t foo_var;
foo_var.content = 'g';
return 0;
}
I.e. use content_type_name__ instead of element_type_name__
Proof of compilation
I posted in a comment because I thought it was too trivial, but here it is:
Surely you are not just pasting that quoted code into gcc, are you? You can't just execute code outside any function. Put the last line inside a function.
simply put the last two lines of code into main()
or any function it will work for sure.

Token-pasting operator (##) is eating spaces in my C++ macro

I was having trouble with the following macro, and I found out that the token-pasting operator (##) is eating the space between static and the return type:
#define MY_FUNCTION(aReturnType) static ##aReturnType MyFunction() { }
So the preprocessor was turning this:
MY_FUNCTION(bool)
into this:
staticbool MyFunction() { }
which caused weird compilation errors.
I came up with the idea of putting parentheses around the static keyword:
// This works but is kind of weird
#define MY_FUNCTION(aReturnType) (static) ##aReturnType MyFunction() { }
Are there any better solutions?
I think that your problem is that you don't want to use token pasting here. If you change the macro to
#define MY_FUNCTION(aReturnType) static aReturnType MyFunction() { }
Then if you write
MY_FUNCTION(bool)
it will expand out into
static bool MyFunction() { }
I am assuming that this is what you want to do, since I can't see what you're trying to paste the aReturnType argument to the macro onto.
Hope this helps!
As it should do? You told it to paste together static and bool. If you don't want that and you want static bool instead, then don't paste them together?

C++ preprocessor and overloading issues

I have the following problem:
Let's consider we have
#define SET callMe
#define COLUMN(x) #x
and in our main block of our program we have the following line:
SET(COLUMN(price)="hi"); which after the preprocessor running is translated to:
#callMe("price"="hi");
I need function callMe signature to be callMe(string str) so that leaves us to have to make something to make the "price"="hi" to "price=hi" and let callMe function to handle the rest of the problem. Last thing to state is that all this program I describe is a part of a Table class.
The only option I have is overload the operator = so the "price"="hi" translated to the wanted one, but I can't get what I should overload because I first thought that doing the following overload
#std::string operator=(std::string str) as a member function of the Table class but it seems I can't get it right on track.
Any clues of how I can achieve the wanted operations?
Is this any good to you?
#define SECOND_PASS(x) callMe(#x)
#define COLUMN(x) x
#define SET(x) SECOND_PASS(x)
which results in:
callMe("price=\"hi\"");
This essentially gets the preprocessor to remove COLUMN before converting to a string.
To get what you want, you would have to write your code as SET(COLUMN(price)"=hi").
You can't overload operator=() for a built-in type. This is done for sanity maintenance, among other reasons.
C++ overloading is not intended to allow you to force the compiler to parse a different language.
P.S. Overloading operator=() in the Table class only handles the case where a Table is on the left-hand side of the =. That would require COLUMN(x) to return a Table object, probably not what you want. You could use an adaptor class to get this effect, but the syntax of COLUMN(x) doesn't include which table this column is from, so you're stuck there too.
One way out there solution would look something like this:
class ColumnSetter
{public:
ColumnSetter(const char* name): name(name), value(0) {}
ColumnSetter& operator=(const char* value_) { value = value_; }
operator std::string const &() const { std::string result(name);
if(value) { result.append('='); result.append(value); } return result; }
private:
const char* name;
const char* value;
};
#define COLUMN(x) ColumnSetter(#x)
void callMe(const std::string& param);
Reformat and de-inline to whatever coding standards you have.
You mean like
#define SET(x) (CallMe(x))
ps - usual disclaimer about using the preprocessor
This should be done with classes that overload the various logical operators to create an abstract syntax tree instead of actually performing the operation. Then you can express various SQL expressions as C++ code and get an abstract syntax tree out which can then be serialized into an SQL WHERE clause.
This isn't very hard, and if you are careful about it, it will be pretty efficient. It's much better than trying to use preprocessor hackery to create an SQL expression builder.

Enum declaration inside a scope that is a parameter of a macro

I am trying to create a macro that takes a scope as a parameter.
I know, it is probably not a good thing etc etc.
I was trying this and got the problem that preprocessor looks for commas and parentheses... the problem is with enum.
How would I declare a enum inside a scope that is a parameter of a macro?
when the compiler see the comma between enum itens, it takes it as a separator.
If you are curious to know why I entered into this, is because I need to register my namespaces and classes, for namespaces I need to know when they are closed, so I was thinking to create a macro that initially calls a static function that register the namespace, encapsulate its contents and finally call a static function that removes the namespace from the registry.
With a macro it would be easier for the coder to do this and make sure he doesn't forget to remove the namespace in the end of the bracket.
Thanks,
Joe
EDIT:
I want a macro that accepts a scope as parameters:
#define MYMACRO(unkownscope) unknownscope
class MYMACRO({
// please, don't take this code seriously, it is just an example so you can understand my question
});
now, if I try:
#define MYMACRO(unkownscope) unknownscope
class MYMACRO({
enum {
anything = 1,
everything = 2
};
});
it won't compile because of the comma inside the enum, because the compiler thinks it is a separator of the macro. It doesn't happen with commas inside parentheses, example:
int a(){
int x = anyfunction(1, 2);
}
would compile normally because the comma is inside a double parentheses.
Sorry for not being able to explain earlier... my english is not that good and the words just keep skipping me =[
Ty for the answers!
Joe
It sounds like you are pushing the preprocessor beyond where it's willing to go. While it's not as elegant, how about breaking your macro in two (one pre- and one post-) and rather then passing a "scope" as parameter, you surround your scope with you pre- and post- macros.
So, if your macro looks something like:
SOMACRO({ ... });
You would instead do something like:
PRESOMACRO();
{ ... };
POSTSOMACRO();
#define SCOPED_STUFF(pre,post) pre; STUFF; post;
#define STUFF enum {a,b,c}
SCOPED_STUFF(a,b)
#undef STUFF
#define STUFF enum {q,r}
SCOPED_STUFF(c,d)
#undef STUFF
You are attempting to replicate RAII with a macro.
#define SCOPE(ns) NamespaceRegistrar _ns_rar(ns);
struct NamespaceRegistrar {
std::string _ns;
NamespaceRegistrar(const std::string& ns) : _ns(ns) { AcquireResource(_ns); }
~NamespaceRegistrar() { ReleaseResource(_ns); }
};
{
SCOPE("Foo")
// stuff
}
I have no idea what you are talking about with regard to enums.
You already noticed what the problem is, an article on boostpro.com sums the problem up.
There are work-arounds, but i'd go for utilizing Boost.Preprocessor.
Without knowing exactly what you're trying to achieve syntactically, something like this might be what you are looking for (edited to PP_SEQ):
#define MAKE_ENUM(Name, Seq) enum Name { BOOST_PP_SEQ_ENUM(Seq) }
MAKE_ENUM(foo, (a)(b)(c));