2011-06-19 15 views
7

Jak mogę uzyskać nazwę największego dostępnego typu w moim kompilatorze? Czy to w ogóle możliwe?
Coś jak:Uzyskiwanie największego dostępnego typu

auto largest = get_largest_type(); 

i auto w moim przypadku byłoby długo długo.

+1

Masz na myśli największy typ pierwotny? A co z 'int [100000]'? To dość duży typ, czy to się liczy?I, oczywiście, po co to jest? – jalf

+0

@jalf tak, mam na myśli największy dostępny typ prymitywu – smallB

Odpowiedz

4

Cóż, w zależności jak bardzo trzeba to można spróbować poważne metaprograming tutaj ...

Po pierwsze, będzie oczywiście wymagała jakiegoś „opakowanie” Definiowanie wszystkie dostępne typy pierwotne, tak tutaj jest :

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; 

Wtedy potrzebny jest sposób to rozwiązać typów w odniesieniu do wielkości, więc po pierwsze, pozwala zdefiniować metafunkcji zdolnego do realizacji stric słaby zamawianie rozmiarach:

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

Teraz algorytm sortowania. Tutaj arbitralnie wybrałem sortowanie scalone, które wymagało 3 innych metapunkcji: pack_cat do łączenia pakietów, łączenia w celu łączenia ich według kolejności i połowę do łamania pakietów w 2 innych paczkach.

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

Wreszcie trzeba będzie metafunkcji za zdobycie ostatniego argumentu paczki, która jest prosta do wdrożenia:

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

Teraz program testowy, aby udowodnić, że cały ten kod śmieci Pisałem tam rzeczywiście działa:

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

Wyjście na maszynie x64 linux używając gcc 4.6, gdzie długo podwójnego jest największy dostępny prosty prymitywny typ:

MATCH! 
+0

to coś. Dzięki. – smallB

0

Przypuszczam, że można napisać mały program, który przetwarza program główny. Mały program może użyć sizeof() do porównania wszystkich typów liczbowych w celu określenia największego. Wtedy zamieniłby symbol "NAJWIĘKSZY" w twoim głównym programie na typ, który był faktycznie największy.

0

Możesz użyć klasy szablonu std::numeric_limits, aby uzyskać informacje dotyczące typów pierwotnych, które mają specjalizacje.

Nie, że na niektórych kompilatorów long double jest większa niż long long chociaż na innych long double jest wielkość double (MSVC).

2

Nie, nie jest to możliwe. Można jednak w zasadzie zagwarantować, że 64-bitowy jest największym typem - nie znam żadnego kompilatora oferującego 128-bitową. W przeciwnym razie poproś użytkownika o podanie go jako parametru szablonu lub użyj specyficznych dla kompilatora definicji, aby utworzyć typedef.

+0

[Istnieje co najmniej jeden] (http://gcc.gnu.org/onlinedocs/gcc/_005f_005fint128.html), ale nie we wszystkich celach. – Damon

+0

Co z typami SIMD? – Simon

+0

Długie podwójne ma 128 bitów na niektórych maszynach. –

2

Dla całkowitych typów tylko, można użyć nagłówka <cstdint>, który pozwala zrobić:

std::intmax_t largest; 

nie jestem świadomy każdej takiej funkcjonalności, która obejmuje pływające wskazuje typy, choć.

Powiązane problemy