我为可变位大小的像素颜色值制作了一个类。无论如何,我得到了它的工作,但有一些奇怪的事情:
#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)
在我标记的行上,我应该能够返回* this但是如果我这样做并尝试使用以下测试进行编译:
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
到uint8_t
这是在MSVC上,有谁知道为什么会这样?
答案 0 :(得分:3)
在您的情况下,当您这样做时:
if (std::is_same<my_type, target_type>::value) {
return *this;
}
my_type
为uint32_t
,target_type
为uint8_t
。因此,std::is_same<my_type, target_type>::value
为false
,因此return *this;
不会被执行。
然而,它将编译!编译器报告错误,因为你肯定不能在一个应该返回*this
的函数中返回c<uint32_t>
(类型c<uint8_t>
),因为它们是不同的类型。
模板函数的每个路径必须对编译有效,即使其中一些路径受到运行时执行保护......
答案 1 :(得分: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
在类型相同的情况下启用第一个函数,在类型不相同的情况下启用所有其他情况中的另一个函数。