2011-06-22 74 views
5

boost :: optional <>對於簡單的數據類型是完美的,但只要用於從類實現接口的類繼承,它會在啓用嚴格別名時失敗。爲什麼boost :: optional失敗繼承虛擬函數的類

例子:

#include <boost/optional.hpp> 

struct MyLine{ 
    double a; 
    double b; 
}; 

class Edge{ 
    public: 
    MyLine toMyLine() const; 
    private: 
    virtual MyLine doToMyLine() const =0; 
}; 

class Wall:public Edge { 
    public: 
    Wall(MyLine const& seg):mMyLine(seg){}; 
    private: 
    MyLine doToMyLine() const{return MyLine();}; 
    MyLine mMyLine; 
}; 

class SimpleWall { 
    public: 
    SimpleWall(MyLine const& seg):mMyLine(seg){}; 
    private: 
    MyLine mMyLine; 
}; 

int main(){ 
//boost::optional<Wall> res;  //fails with strict aliasing error 
boost::optional<SimpleWall> res2; //compiles just fine 
} 

編譯時出錯以下使用gcc 4.4.3版是這樣的:

g++ -c -pipe -Wall -Wextra -Wunused -Wmissing-declarations -Wpointer-arith -Wcast-align -Wwrite-strings -Wredundant-decls -Werror -std=c++0x -O2 -Wall -W -I/usr/local/boost_1_44_0 -o obj/main.o main.cpp 

什麼是解決這個問題的最好辦法。我非常想離開strict-aliasing警告enabled.I'm使用boost版本1.44。

更新:

它變得更糟!請看下面的代碼:

#include <boost/optional.hpp> 

class MyBase{ 
    public: 
    int toFoo() const; 
    private: 
    virtual int doToFoo() const =0; 
}; 

class Child:public MyBase { 
    public: 
    Child(int const& foo):mFoo(foo){}; 
    private: 
    int doToFoo() const{return 0;} 
    int mFoo; 
}; 

int main(){ 
boost::optional<int> optint;  //comment out for surprise 
optint.get();      //comment out for surprise 
boost::optional<Child> res2; 
res2.get(); 
} 

使用gcc版本4.4.3以下這編譯編譯:

g++ -c -pipe -Wall -Wextra -Wunused -Wmissing-declarations -Wpointer-arith -Wcast-align -Wwrite-strings -Wredundant-decls -Werror -std=c++0x -O2 -Wall -W -I/usr/local/boost_1_44_0 -o obj/main.o main.cpp 

如果行標有「//註釋掉的驚喜」被註釋掉了,我得到嚴格的別名警告。我已經至少檢查了20次。這是我見過的最奇怪的事情之一。看起來像boost :: optional初始化某事物。獨立於其模板參數或像gcc一樣理解boost ::只有在使用某種方法調用時纔可選。微不足道的第一。有任何想法嗎 ?

+0

既然你談論嚴格別名,我們可以假設你使用GCC? (這是我知道的唯一一個知道或知道的編譯器) –

+0

@Martin:在做任何其他事情之前,嘗試Boost 1.46.1或1.47測試版;考慮到1.44.0現在已經快一年了,很可能已經確定了這一點。 – ildjarn

+0

什麼是重要?此代碼中是否存在「嚴格別名」的問題? – mattn

回答

4

我在Boost 1.44.0中試過這個程序。 這個問題的原因是不覆蓋doToSegment。

Segment doToSegment(){}; 

應增加常量:

Segment doToSegment() const {}; 
+0

OOP在上面的例子中是一個大錯誤。在原始版本中有一個常量,所以這不是她的問題,但無論如何,我只是修改它 – Martin

+0

嗯......我通過編譯GCC 4.2和Boost 1.44.0。 –

+0

有趣,你打開了-O2?我在上面的線程中添加了精確的編譯器命令。我正在使用gcc版本4.4.3 – Martin