Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting the largest type available

How can I get the name of largest available type in my compiler? Is it possible at all?
Something like:

auto largest = get_largest_type();  

and auto in my case would be long long.

like image 419
smallB Avatar asked Jun 19 '11 15:06

smallB


People also ask

How do you find the largest number?

There is no such thing as a highest possible number. No matter what number you have, there is always a larger one. (For example, you could always add 1 to your number to get a larger number).

How do you find the largest element in an array?

To find the largest element from the array, a simple way is to arrange the elements in ascending order. After sorting, the first element will represent the smallest element, the next element will be the second smallest, and going on, the last element will be the largest element of the array.

How do you find the largest number in an array C++?

To find the largest element, the first two elements of array are checked and largest of these two element is placed in arr[0] . Then, the first and third elements are checked and largest of these two element is placed in arr[0] . This process continues until and first and last elements are checked.


2 Answers

Well, depending on how badly you need this, you can try some serious metaprograming here...

Firstly, you will obviously need some kind of "pack" defining all available primitive types, so here it is:

template<typename... TYPES>
class pack
{};

typedef pack<float, double, long double, unsigned short, unsigned int,
    unsigned long, unsigned long long, short, int, long, long long> primitive_types;

Then you will need a way to sort these types in respect to size, so firstly, lets define a metafunction able to implement a strict weak ordering for the sizes:

template<typename L, typename R>
class smaller
{
    public:
        static const bool value = sizeof(L) < sizeof(R);
};

Now, the sorting algorithm. Here I've arbitrarily chosen merge sort, which required 3 other metafunctions: pack_cat for concatenating packs, pack_merge for merging them according to the order, and halve for breaking packs in 2 other packs.

template<typename, typename>
class pack_cat;

template<typename... L, typename... R>
class pack_cat<pack<L...>, pack<R...>>
{
    public:
        typedef pack<L..., R...> type;
};

template<template<typename, typename> class, typename, typename>
class pack_merge;

template<template<typename, typename> class MF, typename HL, typename... TL, typename HR, typename... TR>
class pack_merge<MF, pack<HL, TL...>, pack<HR, TR...>>
{
    public:
        typedef typename std::conditional<MF<HR, HL>::value,
                typename pack_cat<pack<HR>, typename pack_merge<MF, pack<HL, TL...>, pack<TR...>>::type>::type,
                typename pack_cat<pack<HL>, typename pack_merge<MF, pack<TL...>, pack<HR, TR...>>::type>::type>::type type;
};

template<template<typename, typename> class MF, typename H, typename... T>
class pack_merge<MF, pack<H, T...>, pack<>>
{
    public:
        typedef pack<H, T...> type;
};

template<template<typename, typename> class MF, typename... R>
class pack_merge<MF, pack<>, pack<R...>>
{
    public:
        typedef pack<R...> type;
};

template<typename>
class halve;

template<typename A, typename B, typename... T>
class halve<pack<A, B, T...>>
{
    public:
        typedef typename pack_cat<pack<A>, typename halve<pack<T...>>::L>::type L;
        typedef typename pack_cat<pack<B>, typename halve<pack<T...>>::R>::type R;
};

template<typename T>
class halve<pack<T>>
{
    public:
        typedef pack<T> L;
        typedef pack<> R;
};

template<>
class halve<pack<>>
{
    public:
        typedef pack<> L;
        typedef pack<> R;
};

template<template<typename, typename> class MF, typename P>
class pack_sort
{
    private:
        typedef typename halve<P>::L L;
        typedef typename halve<P>::R R;

    public:
        typedef typename pack_merge<MF, typename pack_sort<MF, L>::type, typename pack_sort<MF, R>::type>::type type;
};

template<template<typename, typename> class MF, typename H>
class pack_sort<MF, pack<H>>
{
    public:
        typedef pack<H> type;
};

template<template<typename, typename> class MF>
class pack_sort<MF, pack<>>
{
    public:
        typedef pack<> type;
};

Lastly you will need a metafunction for retrieving the last argument of a pack, which is straightforward to implement:

template<typename>
class pack_get_last;

template<typename H, typename... T>
class pack_get_last<pack<H, T...>>
{
    public:
        typedef typename pack_get_last<pack<T...>>::type type;

};

template<typename H>
class pack_get_last<pack<H>>
{
    public:
        typedef H type;
};

Now, a test program to prove you that all this junk code I wrote up there actually works:

#include <iostream>
#include <utility>

/* all those metafunctions come here */

int main()
{
    typename pack_get_last<typename pack_sort<smaller, primitive_types>::type>::type largest;

    if(std::is_same<decltype(largest), long double>::value)
        std::cout << "MATCH!\n";
}

Output in a x64 Linux machine using gcc 4.6, where long double is the largest available simple primitive type:

MATCH!
like image 126
brunocodutra Avatar answered Nov 13 '22 17:11

brunocodutra


No, this isn't possible. However, you can pretty much guarantee that 64bit is the largest type- I don't know of any compiler that offers 128bit. Failing that, get your user to pass it in as a template parameter or use compiler-specific defines to make a typedef.

like image 42
Puppy Avatar answered Nov 13 '22 17:11

Puppy