Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I detect if anything but an integer is passed to my class constructor?

Fair and simple: How do I check if anything else but an integer is passed to my class in c++?

If I pass f.e. a char 'a' my class gets number 97 in ascii.

I tried std::numeric_limits but I don't get why it is not detecting integers:

#include <iostream>
#include <limits>

class integerCheck
{
public:
    integerCheck(int value)
    {
       if((value != std::numeric_limits<int>::is_integer))
           return;

       std::cout << value << std::endl;
    }
};

int main()
{
    integerCheck valInt(88);
    integerCheck valChar('a');
    integerCheck valFloat(13.44f);

    return 0;
}

I found this Post working with std::enable_if but I can't imagine there is no way to detect wrong input even in c++20 but wrapping everything in a template.

What am I missing, what should I look/search for to detect anything but an integer value? Thanks upfront

like image 492
Ingo Mi Avatar asked Jun 13 '20 22:06

Ingo Mi


3 Answers

Delete the constructor taking chars and make the ctor explicit to prevent accepting floats as follows

class integerCheck
{
public:
    explicit integerCheck(int value)
    {

        std::cout << value << std::endl;
    }
    integerCheck(char ) = delete;
};

This doesn't allow the two following ctors to compile

integerCheck valChar('a');
integerCheck valFloat(13.44f);

I think the following will be better to prevent all of types except int.

class integerCheck
{
public:
    explicit integerCheck(int value)
    {

        std::cout << value << std::endl;
    }

    template<class T>
    integerCheck(T ) = delete;
};

Notice that the past code doesn't prevent the est of the integral types like long, size_t, short, ...

like image 105
asmmo Avatar answered Nov 08 '22 12:11

asmmo


Something along these lines, perhaps:

class integerCheck
{
public:
    // Arguments of type other than `int` go here.
    template <typename T>
    integerCheck(T) {}

    integerCheck(int value) {
       std::cout << value << std::endl;
    }
};
like image 4
Igor Tandetnik Avatar answered Nov 08 '22 11:11

Igor Tandetnik


Your constructor takes only int values as input. A char is an integral type, so it is implicitly convertible to int. So are floating point types.

And your use of std::numeric_limits<T>::is_integer doesn't work because it is true when T is int, like you are hard-coding. But it would also be true for other integral types too, including char.

If you want to avoid implicit conversions, you could pass the int by a non-const reference, eg

integerCheck(int &value) {
    std::cout << value << std::endl;
}

However, that means you can't pass in integer literals, either. Only int variables.

A better solution is to make integerCheck() use a template parameter, and then you can check the type of the template that the compiler deduces from the input, eg:

#include <type_traits>

template<typename T>
integerCheck(const T &value) {
    if constexpr (std::is_same_v<T, int>) {
        std::cout << value << std::endl;
    }
}
integerCheck valInt(88); // T=int
integerCheck valChar('a'); // T=char
integerCheck valFloat(13.44f); // T=float
like image 5
Remy Lebeau Avatar answered Nov 08 '22 12:11

Remy Lebeau