Domanda

I was just messing about, when I discovered this pre-processor dependent way of creating a template class:

#include <iostream>
#include <typeinfo>

// Is this a valid template class?
#define TEMPLATE_CLASS(T)\
class TemplateClass_ ## T\
{\
private:\
    T value;\
public:\
    void print_type()\
    {\
        std::cout << typeid(T).name() << std::endl;\
    }\
}

class Sample {};

TEMPLATE_CLASS(int) obj1;
TEMPLATE_CLASS(char) obj2;
TEMPLATE_CLASS(Sample) obj3;

int main(int argc, char* argv[])
{
    obj1.print_type();
    obj2.print_type();
    obj3.print_type();
}

I compiled this simply with:

g++ src.cpp -o main.exe

The output:

i
c
6Sample

Now, as you can see, it pretty much works the same way as template classes. Except for the obvious fact than the objects can only be declared globally, since it actually defines a new class inline when you use TEMPLATE_CLASS(T), and new classes cannot be defined within a function. A solution to this can be:

TEMPLATE_CLASS(float);

int main() { TemplateClass_float obj; }

Anyway, this gave me a lot to think about. Firstly, can this even be called a valid generic class? And so, can it possibly be used instead of the standard template feature? Obviously, using the standard template feature is a lot more convenient, but what I mean to say is, will this work just as well? Lastly, does the template feature defined by the C++ standard internally do something similar to what I'm doing with the pre-processor? If not, what are the differences between this implementation and C++'s standard template feature?

È stato utile?

Soluzione

It does the same thing as a template only in the simplest cases. Try doing this with macros:

template <class Ty> class C {};
template <class Ty> class C<Ty*> {};
template <class Ty> class C<std::vector<Ty> > {};

Altri suggerimenti

What you are doing are not templates, but macros. Using macros instead of templates is a good way to shoot yourself in the leg. Here is an example from msdn

//macro
#define min(i, j) (((i) < (j)) ? (i) : (j))

//template
template<class T> T min (T i, T j) { return ((i < j) ? i : j) }

Here are some problems with the macro:

  1. There is no way for the compiler to verify that the macro parameters are of compatible types. The macro is expanded without any special type checking.

  2. The i and j parameters are evaluated twice. For example, if either parameter has a postincremented variable, the increment is performed two times.

  3. Because macros are expanded by the preprocessor, compiler error messages will refer to the expanded macro, rather than the macro definition itself. Also, the macro will show up in expanded form during debugging.

The preprocessor can be used to create macros and if you were using C you might use this to do exactly what you've done. C++ provides templates as part of the language so you can do this and so much more. For example, your macro will not be strongly typed and you'll be missing out on a lot of compile time checking which could pick up bugs that the preprocessor never will.

Using macros rather than templates in nearly all circumstances is not the way to go. Your code will also be difficult to maintain and therefore follow. So, put it another way, if you want your colleagues to think less of you and get annoyed at the mention of your name, go right ahead and use macros. :)

Well, it obfuscates the actual type of the class, thus making it harder to work with functions and such. And it seems that you can't use recursion of templates with your approach, since it defines new class everytime that macro is used. Ontop of that you can't make it Turing complete, because you can't define exception cases for the template class. It also lacks the ability of defining value based template classes :D I think you could list easily more problems, but these may be the major ones.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top