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.
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!
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.
For integer types only, you can use the <cstdint>
header, which allows you to do:
std::intmax_t largest;
I'm not aware of any such functionality that includes floating points types, though.
I suppose to you could write a small program that reprocesses your main program. The small program could use sizeof() to compare all the numeric types to determine the largest. Then would replace the symbol "LARGEST" in your main program with the type what actually was the largest.
You can use the std::numeric_limits template class to get some information regarding the primitive types which have specializations.
Note that on some compilers a long double
is larger than the long long
although on others a long double
is the size of a double
(MSVC).
精彩评论