Почему boost :: option терпит неудачу для классов, наследующих виртуальные функции - PullRequest
5 голосов
/ 22 июня 2011

boost :: option <> отлично работает для простых типов данных, но при использовании для класса, унаследованного от класса, реализующего интерфейс, происходит сбой при включении строгого алиасинга.

Пример:

#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

Как лучше всего решить эту проблему. Я бы очень хотел оставить предупреждение о строгом псевдониме включенным. Я использую версию Boost 1.44.

UPDATE:

Становится хуже !! Рассмотрим следующий код:

#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 :: необязательный инициализирует sth. не зависит от параметра шаблона или типа gcc, получающего понимание boost :: необязательно, только если вызывается с помощью sth. тривиально первое. Есть идеи?

1 Ответ

4 голосов
/ 22 июня 2011

Я пробовал эту программу в Boost 1.44.0. Причина этой проблемы - не переопределять doToSegment.

Segment doToSegment(){};

должно быть добавлено const:

Segment doToSegment() const {};
...