2017-06-10 10 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>(); 

、私はエラーuint32_tの場合ではありませんその同じタイプの場合に何かを変換するために想定されていないので意味がありません

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

を取得

これはMSVCにありますが、なぜそれが起こるのか知っていますか?あなたがあなたの場合は

+0

'cから変換できません'本当に不明な点はありますか? –

+0

あなたは本当にあなたの 'if'文中に2つの返品を返しますか、それとも貧しい人のコメントですか? – erip

+0

@πάνταῥεῖそのシナリオは決して起こりません – user81993

答えて

4

、:

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

my_typeuint32_tあるとtarget_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

特殊なケースなどのために1つのバージョンが有効になっているので、関数全体を複製することができます。それはうまくいくと思います。 – Rook

1

この場合、同じタイプのものと他のタイプの2つのバージョンの関数が必要です。一つの可能​​性:この仕組み

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は種類が同じである場合における第1の機能、および他のすべての場合で、他の機能を可能にするということです。

関連する問題