c++ preprocessor question
category: code [glöplog]
hi
i have this macro:
and when I use it like: REGISTER_ELEMENT(Screen); I get the following error from the compiler (after preprocessing): error C3861: 'newScreen': identifier not found
Any idea on how to keep the spacing between "new" and "##className" ?
i have this macro:
Code:
#define REGISTER_ELEMENT(className)\
Element * Allocate_##className(std::vector<std::string>::const_iterator &i, Bootstrap& b)\
{\
return new ##className(i,b);\
}\
and when I use it like: REGISTER_ELEMENT(Screen); I get the following error from the compiler (after preprocessing): error C3861: 'newScreen': identifier not found
Any idea on how to keep the spacing between "new" and "##className" ?
er, is this a trick question?
just drop the "##" in front of it ffs!
just drop the "##" in front of it ffs!
as i read the documentation the hash signs do the following:
#foo => "foo" vs ##foo => foo
#foo => "foo" vs ##foo => foo
(one being a string literal and the other an identifier)
Nopes, ## is for concat the identifier with f.e. test -> #define TEST(foo) { some_routine(test##foo) } giving TEST(bla) { some_routine(testbla} while "some_routine(testfoo)" would result in some_routine(testfoo) giving a compile error :)
You don't need the hash signs. E.g.:
#define VERY_BAD_WAY_TO_ADD(x, y) x+y
##: "The operator ## concatenates two arguments leaving no blank spaces between them:"
#define VERY_BAD_WAY_TO_ADD(x, y) x+y
##: "The operator ## concatenates two arguments leaving no blank spaces between them:"
btw. I would go for template here ;) avoid the macro...
template <class T> Element* Allocate<T>(std::vectory<std::string>::const_iterator &i, Bootstrap &b) { return new T(i.b); }
template <class T> Element* Allocate<T>(std::vectory<std::string>::const_iterator &i, Bootstrap &b) { return new T(i.b); }
doh, i'll delete the hash signs :-)
Quote:
std::vectory
I like that :) Apart from that, yes, throw away that macro, use the template variant unless you have a very very good reason to use macros (which you almost never have).
@Saga: ?thumb too big error :/ but leading to funny result :)
"Can't avoid Macro, try to avoid Macro if you can".. ok, the catch-version is better *G*
"Can't avoid Macro, try to avoid Macro if you can".. ok, the catch-version is better *G*
Quote:
unless you have a very very good reason to use macros (which you almost never have).
Actually, I recently tried to write a compile time computation of an hash for constant strings using templates. The compiler NEVER ended up computing everything at compile time, it was simply unrolling the computation... In the end, I took the same code, removed the template and wrote a script in python to generate every possible version of the function for strings up to N characters. Only that way the compiler would compute the hash at compile time... It's not C++ preprocessor pre-processed but it is still pre-processed code and it might be possible to write it using macros.
So, no, C++ templates aren't the holy grail for everything.
But I agree that here, they do exactly the same and are prettier :)
Also, sending in a non-const reference to a const_iterator could be seen as rather… odd. (In general, non-const references are pretty confusing beasts, iterators or no iterators.)
Sesse, how is that related?
my goal with the macro is to define the factory functions compile time and registering them with a central factory.
The first part is easy-peasy to do using templates using something similar to what danzig posted.
The latter is a bit more tricky, in my mind, and the current solution is to let the macro generate a unique static variable to ensure the registration to take place at runtime.
Example of defintion:
this unrolls to something similar to
The first part is easy-peasy to do using templates using something similar to what danzig posted.
The latter is a bit more tricky, in my mind, and the current solution is to let the macro generate a unique static variable to ensure the registration to take place at runtime.
Example of defintion:
Code:
class Screen : public Element {... };
REGISTER_ELEMENT(Screen);
this unrolls to something similar to
Code:
class Screen : public Element { ... };
Element * Allocate_Screen(std::vector<std::string>::const_iterator &i, Bootstrap& b) { ... }
static bool isRegistered_Screen = RegisterElement("Screen", Allocate_Screen);
Probably not very helpful, but Google Test does something very similar. They also use macros. Maybe worth a look to see how they do it.
Sesse, how is that related?
rasmus: Well, he did it in his sample code?
Åh, Yes. I left one out in my original post. And sorry for double.post
@Sesse:
I dont get it...
1.) i was just "templating" the macro rasmus posted
2.) for gods sake WHAT DO I KNOW he wants with the const_iterator? maybe iterating the r/o vector in the constructor or whatever... a reference to a const_iterator does not have to be const... const would prevend rasmus from changing i -> for the sake of readable and intuitive code would result in std::string instead of const std::vector<std::string>::const_iterator as param :D
Or did I get you wrong?
I dont get it...
1.) i was just "templating" the macro rasmus posted
2.) for gods sake WHAT DO I KNOW he wants with the const_iterator? maybe iterating the r/o vector in the constructor or whatever... a reference to a const_iterator does not have to be const... const would prevend rasmus from changing i -> for the sake of readable and intuitive code would result in std::string instead of const std::vector<std::string>::const_iterator as param :D
Or did I get you wrong?
Danzig: Dude. It's not a personal attack. You guys posted one thing that was wrong/bad with his code. I'm pointing out another thing.
@Sesse: I dont feel attacked at all :) I always forget that writting CAPS is like "shouting on the net". Im just curios WHAT (ups, I did it again...) you wanted to point out! Its not that I ever pass a const_iterator ref myself ;) but I still dont get your point.
@Danzig: I simply wanted the original author to rethink if this was the best way to do whatever he/she wanted to do. For instance, sending lone iterators into a function is not necessarily wrong, but it's something I've rarely ever seen in solid, well-designed code, and it's hard to imagine exactly what would be accomplished by it that couldn't be done just by sending in either the vector itself or the first element. In short, it smells that there might be a better design of that particular function; nothing more, nothing less.
Why would it be bad? I pass Them around all the time. The idea is that the called functions may read content and advance the iterator from an input stream/container
Ok, this is where elvis left the building :)
?too many discussions about good/bad c++
code error
Nearly EVERY day at work my new coders ask why
the legacy code from excoders is so bull.
Or older coders duplicate code with little changes
instead of using params in one funtion to decide some
differences for the sake of readability and you can not help it.
I am fed up with that,sorry.
Thanks for reading my personal meme :-)
?too many discussions about good/bad c++
code error
Nearly EVERY day at work my new coders ask why
the legacy code from excoders is so bull.
Or older coders duplicate code with little changes
instead of using params in one funtion to decide some
differences for the sake of readability and you can not help it.
I am fed up with that,sorry.
Thanks for reading my personal meme :-)
I love when statements arent backed