Использование boost :: необязательный для константных типов - C ++ - PullRequest
3 голосов
/ 21 февраля 2010

У меня есть контейнерный класс, который использует boost::optional для хранения значения. Вот код выглядит так,

template<typename T>
struct traits
{
    typedef T  value_type;
    typedef T& reference;
};

template<typename T>
struct traits<const T>
{
    typedef const T  value_type;
    typedef const T& reference;
};

template<typename T>
struct traits<T*>
{
    typedef T* value_type;
    typedef T* reference;
};

template<typename T>
struct traits<const T*>
{
    typedef const T* value_type;
    typedef const T* reference;
};

template<typename T>
class container
{
public:

    typedef typename traits<T>::reference reference;
    typedef typename traits<T>::value_type value_type;

    container() {}

    void set(reference value) {
        op.reset(value);
    }

    reference get() const {
        return boost::get(op);
    }

private:
    boost::optional<value_type> op;
};

int main()
{
    foo f;
    container<const foo> c;
    c.set(f);
    return 0;
}

Хорошо работает для других типов, кроме const. Я получаю сообщение об ошибке при использовании const типов (const foo* работает нормально).

  1. Поддерживает ли boost::optional константные типы? Если нет, как я могу обойти эту проблему?
  2. Существует ли готовая реализация черт, которую я могу использовать вместо определения своих черт?

Любая помощь будет отличной!

Ответы [ 2 ]

4 голосов
/ 21 февраля 2010

Проблема не в boost::optional, а в логике того, что вы пытаетесь сделать. Сначала вы создаете контейнер const, а затем пытаетесь изменить содержимое. Я был бы удивлен, если бы это сработало.

Я думаю, что вы, вероятно, должны делать то, что делают стандартные контейнеры (например, vector), и запрещать не копируемые аргументы шаблона.

В противном случае вам придется смириться с тем, что ваш метод set не будет работать, если T не копируется, и предоставить конструктор, который выполняет инициализацию:

class container
{
public:

    container(reference init_value) : op(init_value) {}

};

int main()
{
    foo f;
    container<const foo> c(f);  // OK
    //   c.set(f);  NO
    return 0;
}
0 голосов
/ 21 февраля 2010
template<typename T>
struct traits
{
    typedef T  value_type;
    typedef T& reference;
};

template<typename T>
struct traits<const T>
{
    typedef const T  value_type;
    typedef const T& reference;
};

Разве специализация const не является абсолютно бессмысленной? Без специализации traits<const int> будет иметь const int как value_type и const int& как reference, что именно то, что вы пытались достичь с помощью специализации const, верно?

...