2011-05-08 59 views
3

我已經開始在新的英特爾Sandy Bridge處理器上播放AVX指令。我使用GCC 4.5.2,MinGW64的TDM-GCC 64bit版本。GCC中的矢量類型__m128,__m256與超載衝突

我想超載運營商< < ostream能夠打印出矢量類型__m256,__m128等到控制檯。但我遇到了一個超載衝突。下面的代碼的第二個函數產生一個錯誤「的衝突與早先的聲明void f(__vector(8) float)」:

void f(__m128 v) { 
cout << 4; 
} 

void f(__m256 v) { 
    cout << 8; 
} 

看來,編譯器不能兩種類型區分和consideres他們兩個f(float __vector)

有沒有辦法解決這個問題?我一直無法在網上找到任何東西。任何幫助是極大的讚賞。

回答

4

當功能模板出現類似問題時,我意外地偶然發現了答案。在這種情況下,GCC錯誤信息實際上提出了一種解決方案:

add -fabi-version=4編譯器選項。

這解決了我的問題,希望鏈接標準庫時不會引起任何問題。

人們可以閱讀更多關於ABI(應用程序二進制接口)和GCC ABI Policy and GuidelinesABI specification。 ABI指定代碼編譯爲目標文件時,函數名稱是如何被破壞的。顯然,默認情況下,GCC使用的ABI版本3無法區分各種矢量類型。

+0

請注意,從gcc-5開始,這不再需要,因爲默認的'-fabi-version'已更改。 – 2014-12-04 15:02:00

0

我不滿意改變編譯器ABI標誌來解決這個問題,所以我去尋找一個不同的解決方案。他們似乎在寫本徵庫遇到過這個問題 - 詳見http://eigen.tuxfamily.org/dox-devel/SSE_2PacketMath_8h_source.html

我對這個解決方案是他們的一個輕微扭捏版本的源文件:

template <typename T, unsigned RegisterSize> 
struct Register 
{ 
    using ValueType = T; 
    enum { Size = RegisterSize }; 

    inline operator T&() { return myValue; } 
    inline operator const T&() const { return myValue; } 
    inline Register() {} 
    inline Register(const T & v) : myValue(v) {} // Not explicit 
    inline Register & operator=(const T & v) 
    { 
     myValue = v; 
     return *this; 
    } 

    T myValue; 
}; 

using Register4 = Register<__m128, 4u>; 
using Register8 = Register<__m256, 8u>; 
// Could provide more declarations for __m128d, __m128i, etc. if needed 

使用上面,你可以重載上Register4Register8等等,或者產生模板功能,但不會遇到鏈接問題,也不會改變ABI設置。