Quote:Original post by jdhardy
Quote:Original post by Volte6
Also, These are expanded at run time or compile time? That's why I thought they were like macros.. I thought they were expanded at compile time.
Compile time (unlike Java.NET generics, which are expanded at runtime). The main difference is that templates allow for recursion, are type-checked by the compiler, and are part of the language, and not an add-on like the preprocessor.
Templates exist mainly to avoid some of the problems of macros, but macros can do things that templates can't - and the combination of template metaprogramming and preprocessor metaprogramming is incredibly powerful.
Yes, yes it is. I feel compelled to share something I put together recently (based on something Fruny provided to me in the channel, which in turn comes from the Boost mailing list or something like that):
// introspect.h -- deep magic that I *mostly* understand.
// Remove the spaces after backslashes if you use this.
#ifndef INTROSPECT_H#define INTROSPECT_Htypedef char (&n)[1];typedef char (&y)[2];template< bool condition, typename T> struct enable_if {};template< typename T > struct enable_if<true,T> { typedef T type; };#define INTROSPECT_IMPL(id, ret, func, cflag, ...) \ template< typename T, ret (T::*)(__VA_ARGS__) cflag> struct has_##id##_pfn {}; \ template< typename T > n has_##id##_x(...); \ template< typename T > y has_##id##_x(int, has_##id##_pfn<T, &T::func >* p = 0); \ template< typename T > struct has_##id { \ enum { value = sizeof(has_##id##_x<T>(0)) == sizeof(y) }; \ }#define INTROSPECT(id, ret, func, ...) INTROSPECT_IMPL(id, ret, func,, __VA_ARGS__)#define INTROSPECT_CONST(id, ret, func, ...) INTROSPECT_IMPL(id, ret, func, const, __VA_ARGS__)#define WHEN_AVAILABLE(id, ret) \ template<typename T> typename enable_if<has_##id<T>::value,ret>::type#define WHEN_UNAVAILABLE(id, ret) \ template<typename T> typename enable_if<!has_##id<T>::value,ret>::type#define WHEN_AVAILABLE_INLINE(id, ret) \ template<typename T> inline typename enable_if<has_##id<T>::value,ret>::type#define WHEN_UNAVAILABLE_INLINE(id, ret) \ template<typename T> inline typename enable_if<!has_##id<T>::value,ret>::type#endif
// A usage example:
#include <algorithm>#include <vector>#include <complex>#include "introspect.h"// This was the nicest interface I could acheive - the first parameter for the// INTROSPECT (or INTROSPECT_CONST) macro is a "cookie" which is associated with// the particular introspection we are doing. In this case, symbol "foo" is// associated with objects which provide the member function "void swap(T)",// where T is the object type (you don't get to change this or specify extra// template parameters unfortunately). The other parameters are of course the// return type, function name (it also works with operators), and argument list// (you can specify 'const's and '&'s and so on in there too). INTROSPECT_CONST// is the same except it looks for const member functions instead. INTROSPECT(foo, void, swap, T);// For objects that provide the member function associated with "foo", this// version of fast_swap is instantiated, and declared inline. It is again// templated on T, and returns void (the second parameter to // WHEN_AVAIABLE_INLINE).WHEN_AVAILABLE_INLINE(foo, void) fast_swap(T& a, T& b) { a.swap(b);}// For other types, this other version is instantiated. Thus fast_swap will// call an object's own swap() method if it exists, but otherwise default to// std::swap.WHEN_UNAVAILABLE_INLINE(foo, void) fast_swap(T& a, T& b) { ::std::swap<T>(a,b);}// I also provided plain WHEN_AVAILABLE and WHEN_UNAVAILABLE macros which do// not declare the function inline. The problem is that "inline" has to come// before the return type, but the return type has to be specified in the macro.// Test cases. This is as in the original sample; I suppose it would be more// dramatic to actually initialize some values and output them...int main() { std::vector<int> vector1, vector2; std::complex<int> complex1, complex2; double a,b; fast_swap(vector1, vector2); fast_swap(complex1, complex2); fast_swap(a,b);}
Tested/developed with DJGPP (GXX 3.43).