Find out if a variable is int or float

Hi, guys. I ran into a problem. I'm writing a function (doesn't matter what function it is). The fact is, I don't want to have to just copy the same function so it will work with both float and int, because only one line is the difference.

So I want to add a simple "if" in the middle of the function which will determine whether or not the variable that was passed to the function is int or float.

In the beginning I assumed sizeof(float); would work, but of course it doesn't, since both sizeof(int); and sizeof(float); return a value of 4.
Last edited on
All I did was add .01 to the number and see if it changed the value.
My thinking is that an INT would not change when you add a decimal while a double or float would.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <fstream>
#include <iostream>

using namespace std;

int main (int argc, char *argv[])
{
int test1=101;
double test2=102;
float test3=103;
int test11=0;
double test21=0;
float test31=0;

test11=test1+.01;
test21=test2+.01;
test31=test3+.01;

if (test1==test11)
	{cout << "test1 is INT" << endl;
	cout << test1 << " " << test11 << endl;}
else
	{cout << "test1 is not INT" << endl;
	cout << test1 << " " << test11 << endl;}

if (test2==test21)
	{cout << "test2 is INT" << endl;}
else
	{cout << test2 << " " << test21 << endl;}

if (test3==test31)
	{cout << "test3 is INT" << endl;}
else
	{cout << test3 << " " << test31 << endl;}

return 0;
}
That actually makes sense. I guess I was thinking of something more complicated, but simple is always the best way to go! Thanks!
Er, this is the point of templates.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>

template <typename T>
T do_something( T x, T y )
{
  return (x + y) / 2;
}

int main()
{
  int   a = do_something( 3,   4   );
  float b = do_something( 3.0, 4.0 );

  std::cout << "a = " << a << "\n";
  std::cout << "b = " << b << "\n";
}

If it actually matters, you can test the int/float-ness of the type with the stuff in <type_traits>:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <type_traits>

template <typename T>
void float_or_int( T x )
{
  if (std::is_integral       <T> ::value) std::cout << x << " is an integer type\n"; 
  if (std::is_floating_point <T> ::value) std::cout << x << " is a floating point type\n"; 
}

int main()
{
  float_or_int( -7 );
  float_or_int( -7.0 );
}

Hope this helps.
std::is_same<float, decltype(variable)>::value

type_traits is my personal favorite header.

http://www.cplusplus.com/reference/type_traits/
http://en.cppreference.com/w/cpp/header/type_traits

As JLBorges states below, you should use std::decay as well.
Last edited on
To get the unadorned type, use std::decay<>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <type_traits>

int main()
{
    float f = 5.0 ;
    float& r = f ;
    const float cf = f ;

    std::cout << std::boolalpha
              << std::is_same< float, decltype(f) >::value << '\n' // true
              << std::is_same< float, decltype(r) >::value << '\n' // false
              << std::is_same< float, typename std::decay< decltype(r) >::type >::value << '\n' // true
              << std::is_same< float, decltype(cf) >::value << '\n' // false
              << std::is_same< float, typename std::decay< decltype(cf) >::type >::value << '\n' ; // true
}

http://coliru.stacked-crooked.com/a/a0ceb0ac6b0f813a
Or, if you don't want to use type_traits:
1
2
3
4
5
6
7
8
9
10
11
12
13
float helper(float x){
    return x / 2;
}

template <typename T>
T helper(T n){
    return n * 2;
}

template <typename T>
T f(T a, T b){
    return helper(a + b);
}
Last edited on
Thanks for your answers guys. I had never heard of type_traits before. Sounds interesting. And yeah I tried with templates, but it wouldn't work because:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//Not full program obviously
template<class cond>
int getInt(std::string prompt, cond condition, std::string error)
{
	std::cerr << prompt;
	std::string strNum;
	std::getline(std::cin, strNum);
	
	try
	{
		size_t pos;
		int num = stoi(strNum, std::addressof(pos));
		
		if (all_of(strNum.begin() + pos, strNum.end(), [](char c) { return isspace(c); }) && condition(num))
		{
			return num;
		}
	}
	catch (std::exception) {}

	std::cerr << error;
	return getInt(prompt, condition, error);
}

int main()
{
    int number = getInt("Input: ", [](int num) { return num > 0; }, "Bad input. Try again!");

    return 0;
}


The function is used to validate user input and it returns an int if everything is correct. Using a template to make it work for all types gives me an error (22 of them lol). After which I realized that even if I build the "find the data type" function it would still return an int......
Last edited on
Looks like you're trying to do something similar to: http://www.cplusplus.com/forum/beginner/108849/#msg592118
Thanks, cire and everyone! I managed to fix it somehow :D

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <iostream>
#include <string>
#include <algorithm>
#include <functional>
#include <type_traits>

template<class T>
T getNum(std::string prompt, std::function<bool(T)> condition, std::string error)
{
	std::cerr << prompt;
	std::string strNum;
	std::getline(std::cin, strNum);

	try
	{
		size_t pos;
		T num;

		if (std::is_integral<T>::value == true)
		{
			num = (T)stoi(strNum, std::addressof(pos));
		}
		else
		{
			num = (T)stof(strNum, std::addressof(pos));
		}
		
		if (all_of(strNum.begin() + pos, strNum.end(), [](char c) { return isspace(c); }) && condition(num))
		{
			return num;
		}
	}
	catch (std::exception) {}

	std::cerr << error;
	return getNum(prompt, condition, error);
}

int main()
{
	float choice = getNum<float>("\nEnter float: ", [](float num) { return num > 0; }, "");

	int choice2 = getNum<int>("Enter int: ", [](int num) { return num < 0; }, "");

	std::cout << choice;

	std::cout << "\n" << choice2;

	std::cin.ignore();
	std::cin.get();
	return 0;

}
FWIW (very cursorily tested):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <iostream>
#include <string>
#include <sstream>
#include <type_traits>

namespace detail
{
    template < typename T > T& convert( const std::string& str, T& value, std::ios_base::fmtflags fmtflags )
    {
        std::istringstream stm(str) ;
        stm.flags(fmtflags) ;

        char c ;
        if( stm >> value && stm >> std::skipws && !( stm >> c ) ) return value ;
        else throw std::invalid_argument( "bad value" ) ;
    }

    // overload for std::string
    std::string& convert( const std::string& str, std::string& value, std::ios_base::fmtflags )
    { return value = str ; }

    // overload for const char*
    // etc.

    template < typename T >
    typename std::enable_if< std::is_default_constructible<T>::value &&
                             std::is_move_constructible<T>::value, T >::type
    convert( std::string str, std::ios_base::fmtflags fmtflags )
    {
        T value ;
        return std::move( convert( str, value, fmtflags ) ) ;
    }
}

template < typename T, typename CONDITION >
T& get_a_complete_line( const std::string& prompt, T& value, CONDITION&& cond ,
                        const std::string& err_str, std::istream& stm = std::cin )
{
    {
        std::string line ;
        if( std::cout << prompt && std::getline( stm, line ) )
        {
            try
            {
                detail::convert( line, value, stm.flags() ) ;
                if( std::forward<CONDITION>(cond)(value) ) return value ;
            }
            catch( const std::exception& ) {}
        }
        else throw std::runtime_error( "stream error" ) ;
    }

    std::cerr << err_str << '\n' ;
    return get_a_complete_line( prompt, value, std::forward<CONDITION>(cond), err_str ) ;
}

template < typename T, typename CONDITION >
typename std::enable_if< std::is_default_constructible<T>::value &&
                         std::is_move_constructible<T>::value, T >::type
get_a_complete_line( const std::string& prompt, CONDITION&& cond ,
                     const std::string& err_str, std::istream& stm = std::cin )
{
    T value ;
    return std::move( get_a_complete_line( prompt, value, std::forward<CONDITION>(cond), err_str, stm ) );
}

int main ()
{
    int number = get_a_complete_line<int>( "a number greater than 99 ? ", []( int v) { return v > 99 ; },
                                           "badly formed input" ) ;
    std::cout << "the number is: " << number << '\n' ;

    std::cin >> std::hex ;
    number = get_a_complete_line<int>( "an even integer in hex format ? ", []( int v) { return v%2 == 0 ; },
                                       "you must be joking. please renter the value" ) ;
    std::cout << "the number is: " << std::hex << number << '\n' ;

    std::string str = get_a_complete_line<std::string>( "? ", []( std::string v) { return v.size() < 20 ; },
                                                        "string is too long" ) ;
    std::cout << str << '\n' ;
}
Last edited on
Topic archived. No new replies allowed.