2011-06-22 9 views
5

boost :: optional <> działa idealnie dla prostych typów danych, ale tak szybko, jak jest używana dla klasy dziedziczącej z klasy implementującej interfejs, kończy się niepowodzeniem po włączeniu ścisłego aliasingu.Dlaczego funkcja boost :: optional nie działa w przypadku klas dziedziczących funkcje wirtualne?

Przykład:

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

skompilowany z użyciem następujących gcc w wersji 4.4.3 jest to w przypadku błędu:

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 

Jaki jest najlepszy sposób, aby rozwiązać ten problem. Bardzo chciałbym włączyć ostrzeżenie o wyrównaniu ścisłym. Używam wersji boost 1.44.

AKTUALIZACJA:

Jest coraz gorzej !! Rozważmy następujący kod:

#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(); 
} 

skompilowany z następujących użyciu gcc w wersji 4.4.3 to kompiluje:

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 

Jeśli linie oznaczone „// wypowiedzieć się na zaskoczenie” są komentarzem, ja otrzymasz ostrzeżenie o ścisłym aliasingu. Sprawdziłem to co najmniej 20 razy. To jedna z najdziwniejszych rzeczy, jakie kiedykolwiek widziałem. Wygląda jak boost :: opcjonalne inicjuje coś. niezależnie od jego parametru szablonu lub jak gcc zrozumienie boost :: opcjonalne tylko wtedy, gdy wywołane z czymś. trywialne w pierwszej kolejności. Jakieś pomysły ?

+0

Skoro mówisz ścisłym aliasingu, możemy założyć, że używasz GCC? (Jest to jedyny kompilator, o którym wiem, że wie lub czuje się inaczej) –

+0

@Martin: Wypróbuj Boost 1.46.1 lub 1.47 beta zanim zrobisz cokolwiek innego; jest całkiem prawdopodobne, że zostało to już naprawione, ponieważ 1.44.0 ma już prawie rok. – ildjarn

+0

Co to jest sprawa? Czy istnieje problem "ścisłego aliasingu" w tym kodzie? – mattn

Odpowiedz

4

Próbowałem tego programu w Boost 1.44.0. Powodem tego problemu nie jest przesłonięcie doToSegment.

Segment doToSegment(){}; 

należy dodać const:

Segment doToSegment() const {}; 
+0

OOPs to duży błąd w powyższym przykładzie. W oryginalnej wersji jest const, więc to nie jest kwestia jej, ale dzięki, po prostu zmodyfikowałem ją – Martin

+0

Hmm ... Przeszedłem kompilację z GCC 4.2 i Boost 1.44.0. –

+0

Interesujące, czy włączyłeś -O2? Dodałem dokładną komendę kompilatora w powyższym wątku. Używam wersji gcc 4.4.3 – Martin