简体   繁体   中英

What's a C++ equivalent of Java wildcards?

In Java if you have a class like:

class Box<E>
{
    some code
}

you can do the following using a wildcard:

Box<?> someBox;
someBox = new Box<Integer>();
someBox = new Box<Double>();

Is there a way to do this in C++?

In better words, how can I declare a variable in C++ that can hold either Box<Integer> or Box<Double> or Box<WhateverDataTypeHere> ?

template <typename T> class Box should inherit from a non-template base (let's say class BasicBox ).

Then a pointer to BasicBox can point to objects of the specializations of the derived template:

BasicBox *someBox = new Box<int>;

Or, since in modern C++™ manually managing memory should be avoided, using a smart pointer would be a better idea:

std::unique_ptr<BasicBox> someBox = std::make_unique<Box<int>>();

In addition to HolyBlackCat's excellent answer , I should also mention you do have a couple of other options to achieve a similar effect.

If you have some subset of classes, you can inherit them all from the same base like this:

class Base {

};

class Derived1 : public Base {

};

class Derived2 : public Base {

};

Then, you can create a Box like this:

Box<std::uinque_ptr<Base>> genericBox;

genericBox can now hold any derived, though because of the way C++ works, you probably need to hold it by pointer, reference, or std::unique_ptr . Consequently, this is kind of messy, but works.

Also, I should mention that using this method will not work for types like int or double , so this is probably not useful if you need to use those types.

Better is, if you have access to it, to use std::variant . This will allow you to store a specific set of types:

Box<std::variant<int, double>> genericBox;

This genericBox can hold either a double or an int .

If you don't have direct access to std::variant , there is also a boost::variant which is basically the same thing. Or, if you have access to neither, you do have the option of a union :

union GenericType {
    int myInterger;
    double myDouble;
};

Box<GenericType> genericBox;

Of course, std::variant and boost::variant is better, but this will work for you if you're ever in a situation where you don't have those.

Now, these options will only work if you ever know ahead of time what types you are attempting to store. If you don't know that, you have the option of std::any :

Box<std::any> genericBox;

As with std::variant , there is also a boost::any . You can also implement it yourself if you really have to for some crazy reason. But I wouldn't recommend doing that unless you are doing it for educational purposes or something.

In C++ it's called templating

template <typename T>
class Box {
private:
    T boxcontents;
}

replace T with whatever type you want. Here's some great documentation on the topic

Well, this is not something that someone want but you can use a pointer for basic types like int For classes you can do that or use some base class for all types you may use.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM