开发者

Is it possible to take a type as an argument in a function?

I'm trying to write a function for a database class that is basically just a wrapper around a hash_map of objects (say shap开发者_如何学Ces) indexed by ID numbers that will look up an ID and cast it to the appropriate pointer type.

e.g. I'd like to be able to do something like this:

Circle* shapeToLookup = NULL;
int idNum = 12;
database.lookup(idNum, circleToLookup);
if(circleToLookup != NULL)
{
    // Do stuff with the circle.
}

and have the database know the type of its argument. Is there a way to do this without either overloading the function (lookup(int, Circle*), lookup(int, Rect*), ad nauseum)? Can you declare a function like lookup(int, Shape*) and have it know which type it's given?

Thanks!


template <T>
Database::lookup(int idNum, T TobjectToLookup)
{
    // inside here, T is the type of the object passed in/
}


You can do it with a template.

Edit: new implementation based on the extra information. If mymap is a std::map<int, Shape*>:

template <typename T>
void lookup(int idNum, T* &ptr) {
    auto it = mymap.find(idNum);
    if (it == mymap.end()) {
        ptr = 0;
    } else {
        ptr = dynamic_cast<T*>(*it); // Shape must have a virtual member function
    }
}

Or you might prefer:

template <typename T>
T* lookup(int idNum) {
    auto it = mymap.find(idNum);
    if (it == mymap.end()) {
        return 0;
    }
    return dynamic_cast<T*>(*it);
}

Then call it like Circle *circle = database.lookup<Circle>(123);

Obviously polymorphic containers are a whole heap of fun in themselves, but I'll assume you have that sorted. There may well be a shared_ptr in there somewhere that I've left out.

Old implementation when I thought the DB might store copies of POD:

template <typename T>
void lookup(int idNum, T* &ptr) {
    void *theresult = // something based on idNum

    // some check needed here that theresult really is the right type.
    // how you do this depends on the database, but suppose that
    // the database gives us some integer "type" which indicates the type
    if (type != type_constant<T>::value) {
        ptr = 0;
    } else {
        ptr = static_cast<T*>(theresult);
    }
}

type_constant is an example of "type traits", you implement it like:

template <typename T>
struct type_constant {};

template <>
struct type_constant<Circle> {
    static const int value = 1;
};

template <>
struct type_constant<Rectangle> {
    static const int value = 2;
};

// etc...


Others have explained how to pass a type to a function (by using function templates). I'd like to give another point of view:

It might be even better to introduce a new virtual function on Shape and then move the Do stuff with the Circle part into the reimplementation of that virtual function in the Cricle class.

That way, you remove the need to know the type. You just fetch a Shape object from your database and then call a doStuff() function - and it does the right thing depending on the actual type of the Shape. A good use case for a virtual function. :-)

Of course, this might be more or less simple, depending on what Do stuff actually does.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜