搞乱sizeof(T)的整体类型

时间:2014-08-06 18:13:41

标签: c++ operator-overloading template-deduction

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)

2 个答案:

答案 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都不是一个好主意。

但是,您的代码在整数提升方面没有任何问题。