2016-05-22 6 views
2

ストーリーが少し長いです、この実装を簡素化するために++ 11月14日cを使用することです、元のコードのようにのようなものです:、それは整数のエンディアン普遍的な実装方法

#ifdef _BIG_ENDIAN_ 
#define ENDIANUSHORT(src)  (unsigned short)src 
#define ENDIANULONG(src)  (unsigned long)src 
#define ENDIANUINT64(src)  (unsigned long long)src 
#else 
#define ENDIANUSHORT(src)  ((unsigned short)((((src)>>8)&0xff) |\ 
               (((src)<<8)&0xff00))) 

#define ENDIANULONG(src)  ((unsigned long)((((src)>>24)&0xFF) |\ 
               (((src)>> 8)&0xFF00) |\ 
               (((src)<< 8)&0xFF0000) |\ 
               (((src)<<24)&0xFF000000))) 

#define ENDIANUINT64(src)  ((unsigned long long)((((src)>>56)&0xFF) |\ 
               (((src)>>40)&0xFF00) |\ 
               (((src)>>24)&0xFF0000) |\ 
               (((src)>> 8)&0xFF000000) |\ 
               (((src)<< 8)&0xFF00000000LL) |\ 
               (((src)<<24)&0xFF0000000000LL) |\ 
               (((src)<<40)&0xFF000000000000LL) |\ 
               (((src)<<56)&0xFF00000000000000LL))) 
#endif //_BIG_ENDIAN_ 

template< 
    typename T, 
    typename std::enable_if<std::numeric_limits<T>::is_integer>::type* = nullptr> 
T _endian(T& t) { 
if (sizeof(T) == 2) 
    return ENDIANUSHORT(t); 
else if (sizeof(T) == 4) 
    return ENDIANULONG(t); 
else if (sizeof(T) == 8) 
    return ENDIANUINT64(t); 

return t; 
} 

template<typename T> 
void endian(T& t) { t = _endian(t); } 

int main() 
{ 
    long lv = 123; 
    endian(lv); 
    ...... 
} 

それはうまく動作しますが、そこになどのようなMSVCで警告されている:

static int64_t _endian(int64_t t) { 
    return ENDIANUINT64(t); 
} 

static uint64_t _endian(uint64_t t) { 
    return ENDIANUINT64(t); 
} 

static int32_t _endian(int32_t t) { 
    return ENDIANULONG(t); 
} 

static uint32_t _endian(uint32_t t) { 
    return ENDIANULONG(t); 
} 

static int16_t _endian(int16_t t) { 
    return ENDIANUSHORT(t); 
} 

static uint16_t _endian(uint16_t t) { 
    return ENDIANUSHORT(t); 
} 

static int8_t _endian(int8_t t) { 
    return t; 
} 

static uint8_t _endian(uint8_t t) { 
    return t; 
} 
:T _endian(T & t)は以下のコードと定義を置き換え :その後

warning C4293: '>>': shift count negative or too big, undefined behavior 

はとして洗練しました

  1. 機能の実装が鈍い、冗長とinconciseです: 今警告なし

    が、私が思うには、2つの欠点があります。

  2. たぶん、いくつかのケースは、私は、C++ 11月14日には、それを終了するエレガントで短い実装を提供することができると思い、あなたにどんな考えを持っている

をカバーされていませんか?

ありがとうございました。

+0

あなたはブーストエンディアンライブラリに顔をしているしたい場合があります。 –

+0

あなたの情報をありがとう。ブーストは非常に有名ですが、私の見解では、コードベースの実装を追加したくないので、私はブーストのファンではありません。 –

+0

私は多くの不必要なコードを紹介するファンもいません。ちょうど彼らが何をしたか見てみましょう;-)#1と#2のために –

答えて

4

あなたはC++ 11/14自体は必要ありません。あなたがする必要があるのは

  1. これらのマクロをインライン関数に置き換えます。それだけではなく、次のステップを容易にします。
  2. 上記インライン関数を クラスのメンバーのstatic constexprにする。整数のsize_tをテンプレートパラメータとして受け入れます。
  3. テンプレートを形質クラスに関して実装します。

コード:

template<std::size_t> struct EndianTraits; 

template<> 
struct EndianTraits<2u> 
{ 
    using type = std::uint16_t; 
#ifdef _BIG_ENDIAN_ 
    constexpr static type ToEndian(type val) { return val; } 
#else 
    constexpr static type ToEndian(type val) { return ((((val)>>8)&0xff) | 
                (((val)<<8)&0xff00))); } 
#endif 
}; 

template<typename T, 
     typename = std::enable_if<std::numeric_limits<T>::is_integer>::type> 
T Endian(T t) { 
    using type = EndianTraits<sizeof(T)>::type; 
    return EndianTraits<sizeof(T)>::ToEndian(static_cast<type>(t)); 
} 
+0

、私はそれらを理解することができますが、彼らは#3のように、私はそれが良い解決策かもしれないと思います。例? –

+0

@ ravin.wang、short intに追加されました。しかし、#1と#2は#3を行うために必要なことに注意してください。また、グローバルスコープ内の名前に先頭にアンダースコアを付けるべきではありません。これらの名前は、標準で実装するために予約されています。 – StoryTeller

+0

Teller答えてくれてありがとう、私の質問を解決するようです。正直に言うと、私たちは構造体EndianTraits <2u>、構造体EndianTraits <4u>、構造体EndianTraits <8u>、構造体EndianTraits <1u>、または構造体EndianTraits <1>、構造体EndianTraits <2>、構造体EndianTraits <4>、構造体EndianTraits <8>を定義する必要があるため、コードは、とても簡潔ではないと思います –

関連する問題