Reputation: 1549
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
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;
});
}
Upvotes: 2
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
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