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 ?
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) –
@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
Co to jest sprawa? Czy istnieje problem "ścisłego aliasingu" w tym kodzie? – mattn