boost :: необязательный <> в союзе? - PullRequest
5 голосов
/ 12 января 2011

У меня есть необязательная структура POD, которая будет содержаться внутри объединения.
boost::optional<> содержит его тип по значению, поэтому я подумал, что это может сработать:

union helper
{
    int foo;
    struct 
    {
        char basic_info;
        struct details {
            //...
        };

        boost::optional<details> extended_info;
    } bar;
    //  ...
};

helper x = make_bar();

if( x.bar.extended_info )
{
    // use x.bar.extended_info->elements
}

, но VS2008 пожаловался, что мойbar struct now имеет конструктор копирования из-за элемента boost::optional<details>.

В качестве замены я добавил логический флаг, чтобы указать, допустим ли необязательный параметр, ноэто неуклюже:

union helper
{
    int foo;
    struct 
    {
        char basic;
        struct details {
            bool valid;
            //...
        } extended;
    } bar;
    //  ...
};

Я подумал о реализации details::operator bool() для возврата переменной details::valid, но это неясно и вредно для человечества.
boost::optional<> ясно документирует синтаксис и намерение, и не 'не требует детективной работы.

Наконец, объединение helper должно быть POD, поэтому я не могу выполнять динамическое выделение - иначе я бы использовал указатель.

Любые предложения для чего-либосинтаксически похож на boost::optional<> это можно использовать в союзе?

Ответы [ 2 ]

13 голосов
/ 12 января 2011

Вы не можете использовать не-POD типы в качестве полей в объединении.Используйте boost :: variable или что-то подобное в C ++ вместо union.Оставьте объединение только для совместимости с модулями написанными на C.

0 голосов
/ 13 января 2011

Как уже упоминали другие, идеальная вещь, чтобы сделать, это изменить с union на boost::variant<>.

Однако, если это невозможно, вы можете реализовать POD-аппроксимацию boost::optional<> следующим образом:

Осуществление

template <typename T>
class Optional
{
    T value;
    bool valid;

public:

    // for the if(var) test
    operator bool() const  {  return valid;  }

    //  for assigning a value
    Optional<T> &operator=(T rhs)   
    {  
        value = rhs;  
        valid = true;  
        return *this;  
    }

    //  for assigning "empty"
    Optional<T> &operator=(void *)  
    {  
        valid = false;  
        return *this;  
    }

    // non-const accessors
    T &operator*()   {  return  value;  }
    T *operator->()  {  return &value;  }

    // const accessors
    const T &operator*()  const  {  return  value;  }
    const T *operator->() const  {  return &value;  }
};

Средства доступа к const необходимы, если вы держите экземпляр const Optional<>.

Использование

Как и указатель, Optional<T> не имеет состояния по умолчанию и должен быть инициализирован, прежде чем вы сможете на него положиться (ноль или нет).
В отличие от boost::optional<T>, Optional<T> не может быть создан из его типа значения T, и может быть создан только из другого Optional<T>.
Если вы действительно хотите его инициализировать или обнулить при создании, вы можете создать вспомогательный класс с operator Optional<T>(). Я решил не делать этого.

Строительство

Optional<details> additional_info;
Optional<details> more_info(additional_info);

Назначение

// if there's no additional info
additional_info = 0;

// if there is extended info
details x;
//  ...populate x...
additional_info = x;

Доступ к данным

if( extended_info )
{
    extended_info->member;
    // - or -
    details &info = *extended_info;
}

Так что - все оказалось не так уж плохо. Это не заставляет меня чувствовать себя довольно тепло и нечетко, но это делает работу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...