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.
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.
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!
to coś. Dzięki. – smallB
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.
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).
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.
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ć.
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
@jalf tak, mam na myśli największy dostępny typ prymitywu – smallB