0

私はVisual Studio 2005を使用しており、そのようなメソッド/関数を持っています:

template<typename I>
void MyFunction(I &value)
{
    //some operations
    UI unsigned_type = static_cast<UI>(value);
}

「I」は整数型で、「UI」は適切な使用済み型でなければなりません。たとえば、「I」が 64 ビット整数型の場合、「UI」は 64 ビット符号なし整数型である必要があります。

どうやってやるの?

次に、「I」が常に整数型になることを保証できますか?

第三に、ブーストを使用できません;)。

4

3 に答える 3

3

型特性を自分で実装できます。ライブラリを使用する方が良いかもしれませんが、使用できない場合は、自分で行う必要があります。

template<class T> 
struct make_unsigned; // no implementation

template<>
struct make_unsigned<int>
{
  typedef unsigned int type;
};

template<>
struct make_unsigned<unsigned int>
{
  typedef unsigned int type;
};

// and all other types you need ... (possibly implemented with help of a macro)

そしてあなたのコードで:

template<typename I>
void MyFunction(I &value)
{
    //some operations

    typedef make_unsigned<I>::type UI; 
    UI unsigned_type = static_cast<UI>(value);
}

もちろん、これは完璧ではありませんが、コンパイル時にコードにエラーが表示され、修正することができます。

編集:Iが整数型 (特殊化が存在する型) でない 場合、コンパイルは失敗します。

于 2013-08-12T10:02:24.420 に答える
3

残念ながら、VS2005 ではそれを簡単に行うことはできません (C++11 はそれほどサポートされていないと思います)。C++11 では、が署名さstd::is_signed< I >::valueれているかどうかを確認し、対応する符号なしの型を取得するために使用できます。Istd::make_unsigned< I >::type

于 2013-08-12T09:52:07.907 に答える
3

ブーストを使用できない場合は、いくつかの型特性機構を自分で実装するしかありません。少し面倒かもしれませんが、次の方法で実行できます。

// convinience base classes
template<typename T, T Value>
struct constant { static const T value = Value; };

typedef constant<bool, true> true_type;
typedef constant<bool, false> false_type;

// a trait to check if two types are the same
template<typename T, typename U>
struct is_same : false_type {};
template<typename T>
struct is_same<T,T> : true_type{};

// a trait to check if type is integral, based on is_same
// it's missing wchar_t and bool
#define SAME(T,U) is_same<T,U>::value
template<typename T>
struct is_integral : constant<bool,SAME(T,char) ||
                                   SAME(T,signed char) ||
                                   SAME(T,unsigned char) ||
                                   SAME(T,short) ||
                                   SAME(T,unsigned short) ||
                                   SAME(T,int) ||
                                   SAME(T,unsigned int) ||
                                   SAME(T,long) ||
                                   SAME(T,unsigned long) ||
                                   SAME(T,long long) ||
                                   SAME(T,unsigned long long)> {};

// Trait class to change a type to its unsigned variant.
// The base template simply forwards the type, specializations do the work.

template<typename T>
struct identity { typedef T type; };

template<typename T>
struct make_unsigned : identity<T> {};

template<> struct make_unsigned<signed char> : identity<unsigned char>{};
template<> struct make_unsigned<short>       : identity<unsigned short>{};
template<> struct make_unsigned<int>         : identity<unsigned int>{};
template<> struct make_unsigned<long>        : identity<unsigned long>{};
template<> struct make_unsigned<long long>   : identity<unsigned long long>{};

// Utility class to enable overloads based on some compile time condition
template<bool B, typename = void>
struct enable_if { };
template<typename T>
struct enable_if<true, T> {
    typedef T type;
};

// Only enable this function if I is integral
template<typename I>
typename enable_if<is_integral<I>::value>::type MyFunction(I &value)
{
    typename make_unsigned<I>::type ui;
}

int main()
{
    int i;
    MyFunction(i); // ok
    float f;
    MyFunction(f); // fails
}
于 2013-08-12T10:07:14.460 に答える