Question

I am translating some Java code to C++ but I am having trouble with this function.

private static boolean isArray(Object aObject){
   return aObject.getClass().isArray();
}

Basically, I need to know if an object is a vector of any type and any template. (I am using vectors instead of arrays in my C++ code. )

for example, the output should be something like this.

//define some variables
int a=3;
double arr[]={1.0,2.0,3.0,4.0};
vector<int> vecint ({1,2,3});
vector<double> vecdouble ({1.0,2.0});
Class B {};


//function output:
bool b;

b=function(a); //returns false
b=function(arr); // returns false
b=function(vecint); //returns true
b=function(vecdouble); //returns true
b=function(B); //returns false
Was it helpful?

Solution

In C++, not every thing is an object. A function could take anything, and not everything in C++ is an object. So it's going to be difficult to make a runtime deduction if some random thing being passed to a function is a vector or something completely unrelated. Moreover, it's going to be impossible to declare a function that can take anything, without resorting to void* (please don't), a template, or some kind of variant object.

However we can take advantage of a little template metaprogramming to deduce it at compile time:

#include <cstdlib>
#include <vector>
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;

template <typename Type>
class IsArray;

template<typename Element> class IsArray <vector <Element>>
{
public:
  enum { mValue = true };
};

template<typename Item> class IsArray
{
public:
  enum { mValue = false };
};

int main()
{
    int n = 42;
    cout << "An int is a vector: " << boolalpha << IsArray<int>::mValue << endl;
    vector <int> v;
    cout << "A vector <int> is a vector: " << boolalpha << IsArray<vector<int>>::mValue << endl;
    
}

Output:

An int is a vector: 0
A vector <int> is a vector: 1

Live demo


Actually, this could be simplified further to appear like we're making the deduction at runtime even though it's still being made at compile time:

#include <iostream>
#include <vector>
using namespace std;

template <typename Element> bool IsArray (const vector <Element>& vec)
{
  return true;
}

template <typename Item> bool IsArray (const Item& item)
{
  return false;
}

int main()
{
    int n = 42;
    cout << "An int is a vector: " << boolalpha << IsArray (n) << endl;
    vector <int> v;
    cout << "A vector <int> is a vector: " << boolalpha << IsArray (v) << endl; 
}

Output is the same.

Live Demo

OTHER TIPS

This is taking advantage of Java's design (mainly that everything is derived from Object). C++ has no such requirement. When you declare a std::vector, it is a vector. If not, it isn't. Unless you have a terrible function declaration that takes a void*, you'll need to specify the type of the parameter the function takes (either explicitly or via a template).

You need to use a type trait. What I mean is, the compiler knows the type when it's compiling your code, and it will apply it to the appropriately overloaded function(or constructor in this case), and you can use that to your advantage. Let's make a type trait for a vector.

//A type trait for a vector
template <typename T> struct Is_Vector                  { static const bool value = false; };
template <>           struct Is_Vector<std::vector<T>>  { static const bool value = true;  };

You give the type Is_Vector a vector type and it will have its data member value set to true; otherwise, its data member value will be set to false.

Now let's make a function that uses this type trait

// A function that identifies whether the argument is a vector or not
template <typename Type>
bool isVector(Type object){
    return Is_Vector<Type>::value;
}

Testing it out:

int main(){
    std::vector<int> vector;
    int integer;

    std::cout << std::boolalpha;
    std::cout <<  isVector(vector) << '\n';
    std::cout <<  isVector(integer) << '\n';
}

Produces true for the first function and false for the second. Best thing is, the type is figured out at compile time.

Live Demo


Alternatively, you can accomplish this using two templated functions, one of which is specialized.

//the compiler will choose this one if you pass in a vector
template <typename T>
bool isVector(std::vector<T> vector_object){
    return true;
}

//the compiler will choose this one if you pass in something other than a vector
template <typename T>
bool isVector(T everything_else){
    return false;
}

Live Demo

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top