2017-06-10 99 views
3

我正在製作可變位大小像素顏色值的類。不管怎麼說,我得到了它的工作,但有一個奇怪的現象:在我標線錯誤無法訪問時,爲什麼此程序無法編譯?

#pragma pack(push, 1) 
template <typename my_type> 
struct c { 
    my_type x; 

    c() {} 
    c(my_type x) { this->x = x; } 

    template<typename target_type> 
    c<target_type> convert() { 
     if (std::is_same<my_type, target_type>::value) { 
      return *this; //<- doesn't work 
      return *reinterpret_cast<c<target_type>*>(this); //<- does work 
     } 

     int target_size = sizeof(((c<target_type>*)0)->x); 
     int my_size = sizeof(x); 

     if (my_size < target_size) { 
      return c<target_type>(x << (target_size - my_size) * 8); 
     } 

     my_type rounder = ((x >> (my_size - target_size) * 8 - 1) & 9) > 4; 
     return c<target_type>((x >> (my_size - target_size) * 8) + rounder);  
    } 

}; 
#pragma pack(pop) 

,我應該能夠僅僅返回*這一點,但如果我這樣做,並嘗試用下面的測試來編譯:

c<uint8_t> a; 
c<uint32_t> b(2147483647); 
a = b.convert<uint8_t>(); 

然後我得到的錯誤

cannot convert from c<uint32_t> to c<uint8_t> 

這是沒有意義的,因爲它是不應該,如果任何東西轉換它的同類型這是不符合uint32_t到的情況下

這是在MSVC上,有誰知道爲什麼會發生?

+0

'不能從c 轉換爲c '呃,你不能,實際上不清楚的是什麼? –

+0

你的「if」陳述中是否真的有兩個回報?或者是一個窮人的評論? – erip

+0

@πάνταῥεῖ該場景永遠不會發生 – user81993

回答

4

在你的情況,當你這樣做:

if (std::is_same<my_type, target_type>::value) { 
    return *this; 
} 

my_typeuint32_ttarget_typeuint8_t。所以,std::is_same<my_type, target_type>::valuefalse,所以return *this;將不會被執行。

但是,它會是編譯!而編譯器會報告錯誤,因爲你絕對不能返回*this(類型c<uint32_t>),在應該返回一個c<uint8_t>,因爲他們是不同類型的函數...

模板函數的每個路徑必須是有效的編譯,即使有一些是針對運行時執行...

+0

我被這無數次的咬傷了。 ['std :: enable_if'](http://en.cppreference.com/w/cpp/types/enable_if)一直是我的解決方案,儘管可能會有更好的解決方案。 – Rook

+0

@Rook:我沒有提到,因爲我不確定這將如何幫助解決這個特定問題。 – jpo38

+0

你可以採取複製整個功能的蠻力,爲特殊情況啓用一個版本等。我認爲這應該起作用。 – Rook

1

在這種情況下,你需要什麼樣的保護有兩個版本的功能,一個用於相同類型和另一個用於其它類型。一種可能性:

template<typename target_type> 
typename std::enable_if<std::is_same<my_type, target_type>::value, c<target_type> >::type 
convert() { 
    return *this; 
} 

template<typename target_type> 
typename std::enable_if<!std::is_same<my_type, target_type>::value, c<target_type> >::type 
convert() { 
    int target_size = sizeof(((c<target_type>*)0)->x); 
    int my_size = sizeof(x); 

    if (my_size < target_size) { 
     return c<target_type>(x << (target_size - my_size) * 8); 
    } 

    my_type rounder = ((x >> (my_size - target_size) * 8 - 1) & 9) > 4; 
    return c<target_type>((x >> (my_size - target_size) * 8) + rounder);  
} 

這是如何工作的是,std::enable_if能夠在類型相同的情況下,第一功能,並在所有其他情況下,其他功能時的類型是不一樣的。

相關問題