0

I found some questions that would be in connection with mine, but they did not really answer my question. In Java and C# we have an "object" data type (or in C# the "var"), which can store like anything. For example, I want to use a 2-dimensional array, with its type set to object, so i can store integers and strings in it as well. But I really miss this from C++. As far as I know, in C++ there are templates, but I don't really know how do they work.

template <class T>
T t[] = {1, "2"};

This gives an error. I know about lists, but I would like to use arrays, if possible.

Alihossein shahabi
  • 4,034
  • 2
  • 33
  • 53

2 Answers2

1

In C#, every object that can be identified by a reference starts with the same kind of header which includes information about its type, whether it has been associated with a monitor lock, etc. This makes it possible to have methods that can receive any kind of references and perform certain actions upon the objects identified thereby without having to know or care about the types of the references.

In C++, it is possible to have types which don't have any header--just raw data. Some such types are called PODS (Plain Old Data Structures) and can support some operations that could not be done safely with other types. There is no general concept, however, of objects that share a common style of header. Even though many non-PODS types do support at least one common feature that would require some kind of header (the ability to check whether a base-class pointer can be safely cast to a derived-class object) there is no guarantee that the header contain information sufficient to uniquely identify an object's class. If X1 and X2 both derive from X0, and likewise Z1 and Z2 from Z0, an implementation could simply store 0 in the header for X0 and Z0), 1 for X1 and Z1, and 2 for X2 and Z2. Since an X0* couldn't be possibly identify an Z1, and a Z0* couldn't identify an X1, there's no need to have the header distinguish between X1 and Z1.

Because there is no standard header that can uniquely identify the type of an object, there is no general way to have a function receive a pointer to an object of arbitrary unknown type and do anything useful with it.

supercat
  • 77,689
  • 9
  • 166
  • 211
  • And more fun, trying to do this in C++ without pointers is a one-way trip to [object slicing](https://stackoverflow.com/questions/274626/what-is-object-slicing). – user4581301 Apr 30 '18 at 19:03
  • The system to verify the safety of casting from base type to derived type is only supported for polymorphic types, and even then only if RTTI is enabled. I wouldn't count it as "one common feature" non-POD types share. – François Andrieux Apr 30 '18 at 19:07
  • @FrançoisAndrieux: I thought try-casting from a base type pointer to a particular derived type pointer was guaranteed by the core language to be safe if the pointer identifies any object derived from the base type. Whether or not one regards that as a "common feature", my intent is to emphasize the lack of real and useful common features by identifying the closest thing to such a feature and observing that even that isn't much of a feature. – supercat Apr 30 '18 at 19:16
  • @supercat That doesn't apply to non-[polymorphic types](http://en.cppreference.com/w/cpp/language/object#Polymorphic_objects). You need a `virtual` member function in your class hierarchy. As such, many class types in c++ are incompatible with that use of `dynamic_cast`. It will still succeed in several cases, such as for derived-to-base conversion, but these conversion can be determined statically and don't need runtime information. – François Andrieux Apr 30 '18 at 19:20
  • @FrançoisAndrieux: My primary point was that there exists a category of types for which C++ would have to include some kind of header, but it does not include headers on all such types, and even among types that need a header, it may only be usable by code that knows what base class to expect. These features together preclude the possibility of general-purpose methods that can use all kinds of objects in type-agnostic function. – supercat Apr 30 '18 at 19:40
  • @supercat I agree with the spirit of the answer. My comment is meant to address the line *"Even though non-PODS types do support at least one common feature..."* where the feature you describe is not supported by all non-POD types. – François Andrieux Apr 30 '18 at 19:42
  • @FrançoisAndrieux: Would changing it to "many non-PODS" types be better? – supercat Apr 30 '18 at 19:48
  • @supercat If feel like it would. – François Andrieux Apr 30 '18 at 19:51
0

Here is a short bit of C++ code that will do what you are asking. I think. Sometimes just seeing an example is helpful. I think the site cppreference.com is your friend here. There are many good examples to illustrate usage.

#include <iostream>
#include <variant>
#include <array>

int main()
{
//  Note this will also work:
//  std::variant<int, std::string> t[] = { 1, "2" };

    using node = std::variant<int, std::string>; 
    std::array<node, 2> t = { 1, "2" };

    std::cout << "t[0]: " << std::get<int>(t[0]) << std::endl;
    std::cout << "t[1]: " << std::get<std::string>(t[1]) << std::endl;

    return 0;
}
natersoz
  • 1,674
  • 2
  • 19
  • 29