打印多种不同类型的数字限制

Print numeric limits for multiple, varying types

本文关键字:数字 同类型 打印      更新时间:2023-10-16

在下面的代码中,我定义了一个名为 my_typeunsigned int,我用它来打印类型本身的最大值:

#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;
}

如何对多种类型执行相同的操作而不必复制此代码?

我尝试创建一个字符串数组来存储unsigned intlong类型(例如),但这不起作用:

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();
}

我也尝试过使用模板,但不知道该怎么做。

这可能吗?

#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;
}

和:

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

C++没有反射,因此无法将 C++ 字符串转换为类型名称。但是,您可以使用可变参数模板来完成任务。

#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;
}

更新

更复杂的例子。

您可以声明用于保存类型列表的可变参数模板:

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;
};

和模板来执行操作,取决于类型列表中每个元素的类型:

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>()();
    }
};

现在,您可以使用 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;
    }
};

并将其与您的类型列表一起使用:

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;
}
您可以使用

boost::variant来通知所需的类型,boost::mpl::foreach遍历它们以及一个函子,用于以 C++11 之前的方式或使用 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;
    });
}

现场示例