class Foo
{
public:
Foo(const void* data) : m_dataPtr(data) {}
template<typename T>
const T Get() {
const T* readPoint = static_cast<const T*>(m_dataPtr);
m_dataPtr = (const char *) m_dataPtr + sizeof(T);
return *(readPoint);
}
private:
const void* m_dataPtr;
};
我得到了上面的课程,现在我想为operator>>
添加一个重载,以便我可以这样做:
Foo foo("Hello World");
int8_t firstChar; // I want to get the first Char
int16_t firstShort; // Get the 2 next bytes
foo >> firstChar;
foo >> firstShort;
所以我创建了这个重载函数:
template<typename T>
void operator>>(Foo& lhs, T& rhs)
{
rhs = lhs.Get<T>();
}
但我不确定它是否有效,因为整数类型转换为int
然后搞砸了sizeof(T)
答案 0 :(得分:2)
快速实验表明您的代码按预期工作。我没有看到任何地方发生任何不良的“促销活动”。究竟是什么让你相信某些东西在你的测试中被提升为int
?
我看到的唯一问题是
m_dataPtr += sizeof(T);
其中m_dataPtr
被声明为const void *
指针。无效指针不支持指针运算。表达意图的正确方法是
m_dataPtr = (const char *) m_dataPtr + sizeof(T);
在C ++语言中,积分促销只发生在一组特定的内置运算符中。这似乎都不是您的代码中的问题。当您在>>
中使用重载的foo >> firstChar
运算符时,不会进行整数提升,模板参数推断将会看到所有相关对象的原始类型。
答案 1 :(得分:1)
const T* readPoint = static_cast<const T*>(m_dataPtr);
上述行会产生对齐问题。
要在没有对齐问题的情况下解决此问题,请创建T
,断言T
是POD(C ++ 03中的普通旧数据)或标准布局(在C ++ 11中)。然后执行memcpy
。
template<typename T>
T Get() {
// C++11:
static_assert(
std::is_standard_layout<T>::value,
"Blitting non-standard layout bits doesn't work"
);
// C++03 static assert hack, makes array size 0 if fails:
// bool pod_check[ std::is_pod<T>::value ];
T result;
memcpy( &result, m_dataPtr, sizeof(T) );
m_dataPtr = (const char *) m_dataPtr + sizeof(T);
return result;
}
RVO无论如何都会删除副本。
此外,为任何类型const T
返回T
都不是一个好主意。
但是,您的代码在整数提升方面没有任何问题。