2016-05-22 30 views
2

故事有點長,它是整數尾數普遍實施,原來的代碼是一樣的:如何用C++ 11月14日,以簡化這個實現

#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警告等作爲:

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

然後精製它爲: t替換_endian(T & t)隨下面的代碼定義:

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

現在沒有報警,但我認爲有2個缺點:

  1. 功能的實現是枯燥的,冗餘和inconcise。
  2. 也許有些情況下,不包括

我認爲C++ 11月14日可以提供一個優雅和短期實施完成它,你有什麼想法?

感謝。

+0

你可能想看看進入升壓字節序庫。 –

+0

感謝您的信息。 boost是非常有名的,但從我的觀點來看,我不想引入額外龐大的代碼庫實現,所以我不是boost的粉絲。 –

+0

我也不介紹很多不必要的代碼。只要看看他們做了什麼;-) –

回答

4

你不需要C++ 11/14本身。你需要做的是

  1. 用內聯函數替換這些宏。這不僅僅是更多的C++系統,它還有助於下一步。
  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

爲#1和#2,我可以理解他們,但他們不是我的重點,至於#3,我想這可能是一個很好的解決方案,你能告訴我一些快速例? –

+0

@ ravin.wang,添加了短整數。但請注意#1和#2是必須要做的#3。另外,你不應該在全局範圍內用東西下劃線來命名東西。這些名稱是由標準爲您保留的。 – StoryTeller

+0

出納感謝您的回答,它似乎解決了我的問題。說實話,我覺得代碼不是那麼簡潔,因爲我們要定義結構EndianTraits <2u>,結構EndianTraits <4u>,結構EndianTraits <8u>,結構EndianTraits <1u>或結構EndianTraits <1>,結構EndianTraits <2>,結構EndianTraits <4>,結構EndianTraits <8> –

相關問題