0
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)

4

2 回答 2

2

一个快速的实验表明您的代码按预期工作。我没有看到任何地方发生任何不受欢迎的“促销”。究竟是什么让你相信某些东西int在你的测试中被提升了?

我看到的唯一问题是

m_dataPtr += sizeof(T);

wherem_dataPtr被声明为const void *指针。void 指针不支持指针运算。表达您的意图的正确方法是

m_dataPtr = (const char *) m_dataPtr + sizeof(T);

在 C++ 语言中,积分提升只发生在一组特定的内置运算符中。在您的代码中,这些似乎都不是问题。当您在 中使用重载>>运算符时foo >> firstChar,不会发生整数提升,模板参数推导将看到所有相关对象的原始类型。

于 2014-08-06T18:23:02.113 回答
1
const T* readPoint = static_cast<const T*>(m_dataPtr);

上面的行会产生对齐问题。

要在不存在对齐问题的情况下解决此问题,请创建一个T,断言Tis 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

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

于 2014-08-06T19:32:08.570 回答