2011-04-19 70 views
2

我将我的代码转移到了Ubuntu 4.4.1 g ++编译器。虽然如下所示超载operator ++ (int),但它会抛出(T*)的错误,但对于(T*&)正常工作。在我的早期版本(linux-64,但不记得确切的版本),它也与(T*)罚款。错误:运算符重载++时需要左值++ - -

任何原因,为什么

template<typename T> 
struct Wrap 
{ 
    void *p; // Actually 'p' comes from a non-template base class 
    Wrap<T>& operator ++() 
    { 
    ((T*)p) ++; // throws error; if changed to (T*&) then ok! 
    return *this; 
    } 
// ... 
}; 
int main() 
{ 
    Wrap<int> c; 
    ++c; // calling prefix increment 
} 
+0

你的意思是为'operator ++(int)'吗? – GManNickG 2011-04-19 05:13:44

回答

2

A型铸造的结果是不是左值,所以它不能分配给和(内置)++是分配的一种形式。这是编译器中的一个错误,如果它曾经工作过。

引用它编译(效果与*(T**)&p相同),但由于别名规则(编译器可能假定不同类型的指针(和引用)不指向同一对象),它在形式上是无效的,尽管它可以用于所有已知的编译器。

它最干净的方式:

p = static_cast<void *>(static_cast<T *>(p) + 1) 

(从来没有使用C++ C样式转换),并依赖于编译器能够准确地编译它以同样的方式为++。然而,如果你在定义指针时使用了模板参数(在你的示例代码中),那么使用正确类型的指针会更好(我会说它也适用于成员指针,但它们没有意义++)。

+1

实际上,最简洁的方法是使用'static_cast'而不是'reinterpret_cast',无效指针转换由' static_cast' in C++。 – AnT 2011-04-19 05:35:04

+0

@AndreyT:谢谢。我将'reinterpret_cast'改为'static_cast'。 – 2011-04-19 05:37:37

+0

'虽然它可以在所有已知的编译器上工作,除了g ++(至少)。编译器使用指向不同类型的指针不能别名的事实非常频繁。 (还有一个事实是指向不同类型的指针可能有不同的大小和表示形式,但这更像是一个理论问题,而不是现在的实际问题。) – 2011-04-19 08:44:03

1

看起来像是在混合你的前缀和后缀增量签名。另外,如果你知道你的类型是T,为什么要使用void *?

适当签名下面参见: http://www.codeguru.com/forum/showthread.php?t=231051

+1

问题在于注释行,而且一个是在普通的旧指针上调用内置的operator ++! (我给你-1,但链接是有用的,虽然它没有回答主要问题) – 2011-04-19 05:22:30