2011-06-22 10 views
5

boost :: optional <>はシンプルなデータ型には最適ですが、インターフェイスを実装するクラスから継承するクラスに使用すると、厳密なエイリアシングが有効な場合に失敗します。仮想関数を継承するクラスに対してboost :: optionalが失敗するのはなぜですか?

例:以下の使用してgccのバージョン4.4.3でコンパイル

#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 
} 

これは誤りである。この問題を解決するための最良の方法です

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 

何。厳密なエイリアシングの警告を有効にしておきたいと思います。私はブーストバージョン1.44を使用しています。

更新日:

悪化します!次のコードを考えてみましょう:

これはコンパイルgccのバージョン4.4.3を使用して、以下でコンパイル
#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(); 
} 

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はsthを初期化するように見えます。そのテンプレートパラメータから独立しているか、stccで呼び出された場合のみboost :: optionalを理解するgccのようになります。簡単な最初。何か案は ?

+0

あなたは厳しいエイリアシングの話をしているので、我々はあなたがGCCを使用していると仮定することができますか? (私が知っているのは、それ以外のことを知っているか気にしている唯一のコンパイラです) –

+0

@Martin:何かをする前にBoost 1.46.1または1.47 betaを試してみてください。 1.44.0がほぼ一歳となっていることを考慮すれば、これはすでに修正されている可能性が高いです。 – ildjarn

+0

問題は何ですか?このコードに「厳密なエイリアシング」の問題はありますか? – mattn

答えて

4

私はBoost 1.44.0でそのプログラムを試しました。 この問題の原因は、doToSegmentを上書きしないことです。

Segment doToSegment(){}; 

はconstとして追加する必要があります:

Segment doToSegment() const {}; 
+0

OOPは上記の例で大きなエラーです。元のバージョンではconstがあるので、これは彼女の問題ではありませんが、とにかく感謝しています。 – Martin

+0

うーん... GCC 4.2とBoost 1.44.0でコンパイルしました。 –

+0

興味深いことに、-O2を入れ替えましたか?上記のスレッドに正確なコンパイラコマンドを追加しました。私はgccバージョン4.4.3を使用しています。 – Martin

関連する問題