2

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>?

Stefan Dimeski
  • 438
  • 4
  • 16
  • 1
    Pointer to base class type? – Jesper Juhl Nov 15 '19 at 18:45
  • 3
    Instead of going down all the way to the variable level, what is the Java code supposed to do? C++ and Java are not the same, and it isn't wise to try and mimic or model C++ code from Java source. – PaulMcKenzie Nov 15 '19 at 18:46

4 Answers4

6

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>>();
HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
1

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.

0

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

Eastonco
  • 95
  • 7
  • 2
    How do you get a single variable that can hold either, for example, `Box` or `Box`? – JaMiT Nov 15 '19 at 19:07
  • @JaMiT This works just like that. You can have multiple objects of type box holding whatever templated type you want: int, double, float, etc. If you're asking how to have a box that holds multiple types, you could create a third class off type J that holds the two boxes of two different types. – Eastonco Nov 15 '19 at 19:50
  • You have not yet mentioned the *variable* that is the focus of the question. Sure, you can have multiple objects, but the question specifically calls out the use of a single variable that can hold objects of different types. How would declare such a variable with your scheme? – JaMiT Nov 15 '19 at 20:20
  • You could make the variable a templated struct that has both objects inside? I'm not sure I'm understanding the question... – Eastonco Nov 15 '19 at 21:02
  • Please simply give a declaration for `someBox` so that the two assignments in the question become valid. – JaMiT Nov 15 '19 at 22:23
-1

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.

Reza Mahdi
  • 98
  • 8