2011-06-19 8 views
7

コンパイラで最大の利用可能な型の名前を取得するにはどうすればよいですか?まったく可能ですか?以下のような
何か:利用可能な最大の型を取得する

auto largest = get_largest_type(); 

と自動私の場合は、長い長いだろう。

+1

あなたは最大のプリミティブタイプを意味しますか? 'int [100000]'はどうでしょうか?それはかなり大きいタイプです、それは数えますか?そして、もちろん、これは何のためですか? – jalf

+0

@ jalfはい、利用可能な最大のプリミティブタイプを意味しました – smallB

答えて

4

さて、あなたはこれを必要とどのようにひどくによっては、あなたがここにいくつかの深刻なmetaprogramingを試すことができます...

はまず、あなたは明らかにそうここにある、すべての利用可能なプリミティブ型を定義する「パック」のいくつかの種類が必要になります:

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; 

その後、サイズに関しては、このタイプをソートする方法が必要になりますので、まず、サイズのstric弱い順序付けを実装することができメタ関数を定義することができます:

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

今、ソートアルゴリズム。ここでは、3つの他のメタ機能を必要とするマージソートを任意に選択しました。パックを連結するpack_cat、順序に合わせてマージするためのマージ、2つの他のパックのパックを分割するための半分です。

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

最後に、あなたが実装するのは簡単ですパックの最後の引数、取得するためのメタ関数が必要になります、今

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

をすべてこのジャンクコードは、私が書いたことを証明するためのテストプログラムをそこまで実際に動作します:

0123:long double型の最大利用できるシンプルなプリミティブ型でのgcc 4.6を使用してのx64 Linuxマシンで

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

出力を、

MATCH! 
+0

それは何かです。ありがとう。 – smallB

0

私はあなたのメインプログラムを再処理する小さなプログラムを書くことができると思います。 小さなプログラムはsizeof()を使用して、すべての数値型を比較して最大値を判断できます。次に、あなたのメインプログラムのシンボル「LARGEST」を実際に最大のものに置き換えます。

0

テンプレートクラスstd::numeric_limitsを使用すると、特殊化されたプリミティブ型に関する情報を取得できます。他人にlong doubledouble(MSVC)の大きさであるが、いくつかのコンパイラlong double

ないようにlong longより大きい。

2

いいえ、これはできません。しかし、あなたはかなり64bitが最大のタイプであることを保証することができます - 私は128bitを提供するコンパイラについてはわかりません。それに失敗した場合は、ユーザーにテンプレート・パラメーターとして渡すか、コンパイラー固有の定義を使用してtypedefを作成させてください。整数型の場合

+0

[少なくとも1つは](http://gcc.gnu.org/onlinedocs/gcc/_005f_005fint128.html)ですが、すべてのターゲットではありません。 – Damon

+0

SIMD型はどうですか? – Simon

+0

一部のマシンでは、long doubleは128ビット長です。 –

2

のみ、あなたが行うことができます<cstdint>ヘッダ、使用することができます:私は、浮動小数点型を含む任意のこのような機能を認識していないよ

std::intmax_t largest; 

を。

関連する問題