Quintin96
Quintin96

Reputation: 25

How to check if a data type is an array? (C++)

So I am currently a student and have run into the following exercise: Write a function that prints the elements in an array. The array is sent to the function by argument. If this argument is not an array, an exception of type invalid_argument must be thrown. Test the function in the main() function.

So my code is currently as follows:

#include <iostream>
#include <exception>
#include <string>

using std::cin;
using std::cout;
using std::endl;
using std::invalid_argument;
using std::string;

template<class T>void printArray(T arr){
    try{
        arr.size();
    }
    catch(...){
        for (int i=0; i < sizeof(arr); i++){
            cout << arr[i] << endl;
        }
    }
    throw invalid_argument("Argument not of type array");
};

int main(){
    string arrChars[5] = {"1", "2", "3", "John", "5"};
    string s = "Jack";
    try{
        printArray(arrChars);
    }
    catch(invalid_argument &e){
        cout << "Error: " << e.what() << endl;
    }

    return 0;
}

This is after already trying other options such as:

template<class T>void printArray(T arr[]){
...
}

Which doesn't allow the program to run either as I cannot pass any arguments to the printArray() function that are not arrays.

My plan with the code is to swap out arrChars and s as the arguments to printArray() in order to determine success off the program.

Upvotes: 2

Views: 7178

Answers (3)

Jithin John
Jithin John

Reputation: 1

"Write a function that prints the elements in an array"

When you say "array", Are we talking about C[] array or std::array.

Assuming that you are talking about std::array you could write a single template method expecting one argument of any type.

If it is std::array that you are talking about then its totally understandable and possible. Here is a possible solution.

Use a dynamic_cast or typeid to check the type of the argument received.

template <typename T> void printArray(const T& arrayArgument) { 

    if (std::array<int>& test == dynamic_cast<std::array<int>&>(arrayArgument))
         {/* do whatever */ }

 }

or

if(typeid(arrayArgument) == typeid(std::array<int>))

Find more information on dynamic_cast and typeid in the following post.

C++ dynamic_cast vs typeid for class comparison

And if you are thinking of using C[] arrays then this post might help you rethink.

Container Classes over legacy C[] arrays

Upvotes: -1

Vlad from Moscow
Vlad from Moscow

Reputation: 310980

Try something like this

#include <iostream>
#include <type_traits>
#include <stdexcept>
#include <vector>

template <class T>
void printArray( const T &a )
{
    if ( !std::is_array<T>::value ) throw std::invalid_argument("Argument not of type array");

    for ( const auto &x : a ) std::cout << x << std::endl;
}

int main()
{
    int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

    try
    {        
        printArray( a );
        printArray( v );
    }
    catch ( const std::invalid_argument &e )
    {
        std::cout << e.what() << std::endl;
    }        
}   

The program output is

0
1
2
3
4
5
6
7
8
9
Argument not of type array

Upvotes: 1

Barry
Barry

Reputation: 303057

If this argument is not an array, an exception of type invalid_argument must be thrown.

That's... a weird thing to want to do in C++. Typically, we'd go for "if this argument is not an array, the code should not compile." But hey, we can do that too. Just write one function overload that takes an array, and one that takes anything:

template <typename T, size_t N>
void printArray(const T (&arr)[N]) {
    // print array of size N here
}

template <typename T>
void printArray(const T& ) {
   throw invalid_argument("Argument not of type array");
}

Upvotes: 9

Related Questions