3

Possible Duplicate:
Template Constraints C++

I am wondering if I can check to see if type T inherits a certain class in my generic/templated methods. I can do this easily in C# using 'where'. For example, in my game engine, I have this concept of a generic manager that is an XNA component. It has a list of drawable objects (Could be entities, particles, etc). So my class definition is like this:

public class LayerableDrawableGenericManager<T> : Microsoft.Xna.Framework.DrawableGameComponent where T : Drawable

So we can only have a generic manager of an object that can be drawn (an object that inherits drawable). We need to be sure of this because in my generic manager, I am calling Draw() on all those T type objects. Without ensuring that the T type object will inherit the Drawable class (which contains the Draw() method), I wouldn't be able to draw my objects.

anyway, Was wondering how this is done in C++. I've googled around for things like "Where C++" and "Where keyword C++" and all my results are things like "where can i learn C++"..

Community
  • 1
  • 1
Prodigga
  • 1,457
  • 1
  • 22
  • 37
  • There are some tricks that allow for this, but typically it just works without it because you will get a compile error if the draw method is called and T doesn't have one. The main downside is that the error messages aren't as clear. – Vaughn Cato Mar 22 '12 at 00:19
  • you searched for `where` I searched for `C++ template type parameter constraints` see the question I show this as duplicate of. – Miserable Variable Mar 22 '12 at 00:19
  • C++ is actually *structurally-typed* and not *nominatively-typed* in this aspect... just replace the T and, if it compiles, hooray! –  Mar 22 '12 at 00:22
  • C++ templates are essentially text substitution mechanisms. If you call function `A` on object `b` and it does not declare that function then the compiler will let you know about it when it generates the implementation for that type. This is why you can do some really powerful (and perhaps nasty) things with C++ templates that you will never be able to replicate in C# using generics. – Ed S. Mar 22 '12 at 00:22
  • 2
    You can add a static assertion based on the typetrait `std::is_base_of`, but you might as well not bother. C# has a different object model from C++, and such constraints are not nearly as relevant in C++ as they are in C#. – Kerrek SB Mar 22 '12 at 00:24
  • @EdS. Do you really need the "perhaps" there? ;-) –  Mar 22 '12 at 00:24
  • @pst: ...probably not :D – Ed S. Mar 22 '12 at 00:25
  • 1
    Templates are specialized at compile time, not runtime like .NET generics. The C++ compile error constrains it, minus the readability, plus the wider usage. – Hans Passant Mar 22 '12 at 00:25
  • @MiserableVariable: You don't know that template constraints is the intent. I don't think this question is a duplicate of that at this point. – Mooing Duck Mar 22 '12 at 00:29

2 Answers2

4

This is typically done in C++ templates by just assuming that the type provides the functionality that you need. For example, consider the following function template:

template <typename T>
int get_value(T const& x)
{
    return x.get();
} 

struct S { int get() const { return 42; } };

If you call get_value(S()), the compiler will instantiate get_value with T = S, and S::get will be called.

If you call get_value(42), the compiler will attempt to instantiate get_value with T = int, but instantiation will fail and you will get a compilation error, because int does not have any member functions (more or less one named get).

James McNellis
  • 348,265
  • 75
  • 913
  • 977
1

Sure. The obvious way is dynamic_cast

template<class T>
bool is_Iinterface(T obj) {
    Iinterface ptr = dynamic_cast<Iinterface>(obj);
    if (ptr == nullptr)
        return false;
    else
        return true;
}

or concisely:

template<class T>
bool is_Iinterface(T obj) {
    return dynamic_cast<Iinterface>(obj)!=nullptr;
}

However, the more common and useful way is to use operator overloading.

template<class T>
void do_task(T obj) {
    //do task on object that doesn't have Iinterface
}
void do_task(Iinterface& obj) {
    //do task on object that does have Iinterface
}
Mooing Duck
  • 64,318
  • 19
  • 100
  • 158