(macros + functions) && (templates) [C++]

Started by
17 comments, last by CTar 18 years, 5 months ago
Quote:Original post by Conner McCloud
Quote:Original post by Roboguy
I would like to point out that macros don't inherently have the problems mentioned. C and C++ macros do, but (for example) Scheme's hygienic macros don't.

Of course, the OP isn't refering to Scheme. So your comment is completely pointless.

CM


No it isn't, I wanted to make sure that they didn't think that macros in general have those problems. That way, if they ever use Scheme, they won't avoid macros for those reasons without really learning anything about them.
Advertisement
hehehe Tell me when you beat it CTar!
Quote:Original post by pulpfist
hehehe Tell me when you beat it TCar!


Beat it? What do you mean?
Quote:Original post by Roboguy
No it isn't, I wanted to make sure that they didn't think that macros in general have those problems. That way, if they ever use Scheme, they won't avoid macros for those reasons without really learning anything about them.

Most language specific advice can be rendered pointless if considering the right alternative language. Disclaimers to that affect are just pointless noise.

CM
@ Roboguy :

I am not using Scheme, as you can see, I said C++.

@ Pulpfist :

Your last reply is completely useless, and your other reply was sort of useless. All you said is that macros have side effects and you told me to use reference which I know a lot about, and wasnt talking about.

@ Everyone else :

Thanks, now I get it. So, this:
#define Add(x, y) ((x) + (y))

is (?) completely (?) identical to this:
template<class T>inline T Add(T x, T y){    return x + y;}

Is that true?

P.S. Does anyone know of any good tutorials on templates? They seem very useful and interesting.
-----------------------------....::::DRAGON BALL Z::::....C<<"+"<<"+"; // Go C++ !!!-----------------------------
Quote:Original post by Conner McCloud
Quote:Original post by Roboguy
No it isn't, I wanted to make sure that they didn't think that macros in general have those problems. That way, if they ever use Scheme, they won't avoid macros for those reasons without really learning anything about them.

Most language specific advice can be rendered pointless if considering the right alternative language. Disclaimers to that affect are just pointless noise.

CM


The argument that macros are bad for the reasons mentioned are probably more language specific than what I said.

Quote:Original post by dudedbz1
@ Roboguy :

I am not using Scheme, as you can see, I said C++.


Did you read what I said? I never said it was advice for what you were trying to do at the moment, but for people who will or are use Scheme. I never thought that you were using Scheme.


Anyway, I'm through derailing the thread. Sorry [smile].
Quote:Original post by CTar
I have created a structure with can give you type "const T&" if sizeof(T)>sizeof(T&) and type "const T" if sizeof(T)<=sizeof(T&).


There are a couple of problems with this. For one, sizeof( T& ) is required to yield the size of T, not the sizeof a reference, so sizeof(T) will always equal sizeof(T&) in C++.

Secondly, it's not just the size of the type which should affect your decision, it's more whether or not the type also has nontrivial copy construction and destruction. For instance, a smart pointer may be the size of a regular pointer, however copying and destroying smart pointers can be costly, since it can imply things like incrementing and decrementing reference counts, etc. Because of this, it can be more efficient to pass by reference. As well, what about types which can't be copied? In such a case, a reference has to be be used regardless of its size and destructor, etc.

Anyway, the simplest rule to follow is that if you are unsure which to use, use a reference to const, since reference arguments are extremely easily optimized away with inlining.

Alternatively, if you are really interested in attempting to determine which method to use, you should check out Boost.CallTraits, which accomplishes the type of logic similar to what you described.
Quote:
Thanks, now I get it. So, this:
*** Source Snippet Removed ***
is (?) completely (?) identical to this:
*** Source Snippet Removed ***
Is that true?

P.S. Does anyone know of any good tutorials on templates? They seem very useful and interesting.


No they are far from equal, first inline is only a suggestion, so the compiler might choose to not inline the template function though it would be very bad if it did. There is also the difference that the preprocessor macro is a replacement of text instead of a function, which could introduce many problems (I can't see any in an add function though) look at rip-off's SQUARE example to see what I mean. Also there is the problem of scope which rip-off also mentioned, but ain't a problem with an add function. The template function is also type-safe meaning that it will say that you passed something wrong if you pass anything, but a type, or a type which don't have add. Lastly the template function can't take to different parameters unless one the second can be converted to the first, this can be solved by a function like this:
template<typename T,typename T2,typename RT>RT Add(T X,T2 Y){    return (X+Y);}

I'm pretty certain this can give you problems with some compilers, which can't identify what to set some of the template arguments to.
Quote:Original post by Polymorphic OOP
There are a couple of problems with this. For one, sizeof( T& ) is required to yield the size of T, not the sizeof a reference, so sizeof(T) will always equal sizeof(T&) in C++.

Secondly, it's not just the size of the type which should affect your decision, it's more whether or not the type also has nontrivial copy construction and destruction. For instance, a smart pointer may be the size of a regular pointer, however copying and destroying smart pointers can be costly, since it can imply things like incrementing and decrementing reference counts, etc. Because of this, it can be more efficient to pass by reference. As well, what about types which can't be copied? In such a case, a reference has to be be used regardless of its size and destructor, etc.

Anyway, the simplest rule to follow is that if you are unsure which to use, use a reference to const, since reference arguments are extremely easily optimized away with inlining.

Alternatively, if you are really interested in attempting to determine which method to use, you should check out Boost.CallTraits, which accomplishes the type of logic similar to what you described.


Thanks for the feedback, I know that you should think of other stuff than size, but for the purposes I'm using it the size is the most important. Anyway a type like this shouldn't be used before profiling so you can just see with what type there is a problem and provide a pass-by-value or pass-by-reference explicit template declaration depending on what the problem was.

Also I second your suggestion to use a const reference if you aren't sure what to use.

This topic is closed to new replies.

Advertisement