Alan
Alan

Reputation: 1549

Print numeric limits for multiple, varying types

On the following code I defined an unsigned int called my_type, which I use to print the maximum value of the type itself:

#include <iostream>
#include <limits>
#include <cmath>
...
using namespace std;

int main() {
  typedef unsigned int my_type;

  const my_type max_int = numeric_limits<my_type>::max():

  cout << max_int << endl;
  return 0;
}

How can I do the same for multiple types without having to duplicate this code?

I tried creating a string array that would store types unsigned int and long (as an example), but that didn't work:

string current_type[2] = {"unsigned int", "long"};
loop{
  typedef current_type[0..1] my_type;
  const my_type max_int = numeric_limits<my_type>::max();
}

I have also tried using templates, but couldn't figure it out how to do it.

Is this even possible?

Upvotes: 1

Views: 136

Answers (3)

hlscalon
hlscalon

Reputation: 7552

You could use boost::variant to inform the types you want, boost::mpl::foreach to loop over them and a functor to print the numeric limits in a pre-c++11 manner or with a c++11 lambda

#include <iostream>
#include <limits>
#include <boost/variant.hpp>
#include <boost/mpl/for_each.hpp>

struct printMaxNumLimits
{
    template<class Type>
    void operator()(Type t) {
        std::cout << std::numeric_limits<Type>::max() << std::endl;
    }
};

int main()
{
    using variant_types = boost::variant<int, double, unsigned int>;

    // pre c++11
    boost::mpl::for_each<variant_types::types>(printMaxNumLimits());

    // c++11
    boost::mpl::for_each<variant_types::types>([](auto t){
        std::cout << std::numeric_limits<decltype(t)>::max() << std::endl;
    });
}

Live example

Upvotes: 2

user2807083
user2807083

Reputation: 2982

C++ has no reflection so you can't convert c++ string to type name. But you can use variadic templates for your task.

#include <iostream>
#include <limits>
#include <cmath>

using namespace std;


template <typename ... Args>
struct TL;

template <typename T>
struct TL<T>
{
    static void print()
    {
        const T max_int = numeric_limits<T>::max();
        cout << max_int << endl;
    }
};

template <typename T, typename ... Args>
struct TL<T, Args...>
{
    static void print()
    {
        TL<T>::print();
        TL<Args...>::print();
    }
};

int main(int , char** )
{
    TL<int, unsigned int, short int>::print();
    return 0;
}

UPDATE

More complicated example.

You can declare variadic template for holding type lists:

template <typename ... Args>
struct TypeList;

template <typename T>
struct TypeList<T>
{
    typedef T type;
};

template <typename T, typename ... Args>
struct TypeList<T, Args...>
{
    typedef T type;
//    typedef TypeList<Args...> rest;
};

and template to perform operation, depended of type for each element in type list:

template <typename L, template <typename T> class Op>
struct ForEach;

template <typename T, template <typename T> class Op>
struct ForEach<TypeList<T>, Op>
{
    void operator()()
    {
        Op<T>()();
    }
};

template <typename T, template <typename T> class Op, typename ... Args>
struct ForEach<TypeList<T, Args...>, Op>
{
    void operator()()
    {
        Op<T>()();
        ForEach<TypeList<Args...> , Op>()();
    }
};

Now, you can declare some functions like templated structs with operator()

#include <iostream>
#include <limits>
#include <cmath>

using namespace std;

template <typename T>
struct PrintNumericTypeMaxLimit
{
    void operator()()
    {
        const T max_int = numeric_limits<T>::max();
        cout << max_int << endl;
    }
};

template <typename T>
struct PrintNumericTypeMinLimit
{
    void operator()()
    {
        const T min = numeric_limits<T>::min();
        cout << min << endl;
    }
};

And use it with your type list:

int main(int , char** )
{
    typedef TypeList<int, unsigned int, long int, short int, unsigned short int, double> myList;
    ForEach<myList, PrintNumericTypeMaxLimit>()();
    ForEach<myList, PrintNumericTypeMinLimit>()();
    return 0;
}

Upvotes: 2

feuGene
feuGene

Reputation: 4001

#include <iostream>
#include <limits>

using namespace std;
template <typename T>
void printMax()
{
    cout << numeric_limits<T>::max() << endl;
}

int main()
{
    printMax<unsigned int>();
    printMax<double>();
    return 0;
}

And:

$ g++ test.cpp && ./a.out
4294967295
1.79769e+308

Upvotes: 5

Related Questions