Правильная поддержка изменяемого классификатора функций-членов в STL

Неправильная поддержка летучая квалификация перегрузки функций-членов в СТЛ предотвращает использование контейнеров, умных указателей и т. д. в общем виде. Скажем, я хочу объявить класс-оболочку, который обеспечивает семантику значений и допускает неполноту базового типа:

#include <type_traits>
#include <utility>
#include <memory>

template< typename type >
struct recursive_wrapper
{

using value_type = type;

template< typename ...arguments >
recursive_wrapper(arguments &&... _arguments)
: storage_(std::make_unique< type >(std::forward< arguments >(_arguments)...))
{ ; }

operator type & () & noexcept
{
return *storage_;
}

operator type const & () const & noexcept
{
return *storage_;
}

operator type && () && noexcept
{
return std::move(*storage_);
}

operator type const && () const && noexcept
{
return std::move(*storage_);
}

operator volatile type & () volatile & noexcept
{
return *storage_;
}

operator volatile type const & () volatile const & noexcept
{
return *storage_;
}

operator volatile type && () volatile && noexcept
{
return std::move(*storage_);
}

operator volatile type const && () volatile const && noexcept
{
return std::move(*storage_);
}

private :

std::unique_ptr< type > storage_;

};

// file:main.cpp
#include <iostream>
#include <vector>

#include <cstdlib>

int
main()
{
struct A;
struct B { recursive_wrapper< A > a; };
struct A { std::vector< B > b; };
{ // basic usage
B b;
A & a = b.a; // OK
static_cast< void >(a);
}
// let's add cv-qualifiers
{
volatile B b;
volatile A & a = b.a; // error!
static_cast< void >(a);
}
return EXIT_SUCCESS;
}

Отсутствие подходящего летучая квалификация перегрузка std::unqie_ptr::operator * () вызывает ошибку:

main.cpp:38:16: error: indirection requires pointer operand ('volatile std::unique_ptr<A>' invalid)
return *storage_;
^~~~~~~~~
main.cpp:83:30: note: in instantiation of member function 'recursive_wrapper<A>::operator volatile A &' requested here
volatile A & a = b.a;
^
1 error generated.

Та же история WRT std::container::push_back(), size(), так далее.

Это полностью предотвращает использование объектов СТЛ (не включая const_cast оператор) в общем коде, который использует volatile квалификатор функции-члена.

В чем причина такого бедного СТЛ дизайнерское решение? Зачем volatile Спецификатор функции-члена не поддерживается должным образом в СТЛ?? Является volatile функция-член ограничена?

0

Решение

Это очень хорошо решение. Это потому, что волатильность будет совершенно неправильно для большинства типов.

Имейте в виду, что volatile на объекте значит поля объекта могут изменяться спонтанно.
Рассмотрим следующее и предположим, что система гарантирует, что в любой данный момент begin а также end будет указывать на тот же блок памяти:

template<class T>
class vector
{
T *begin;
T *end;
vector(vector const volatile &other) : begin(other.begin), end(other.end) { ... }
};

Оказывается vector::vector(vector const volatile &) является неправильно, потому что это не может гарантировать, что begin а также end читаются одновременно.
Следовательно, создаваемая им копия может иметь begin а также end которые не синхронизированы, хотя оригинал был полностью в порядке.

Я думаю, этого должно быть достаточно, чтобы вы поняли, почему volatile едва используется.
Он просто не используется по той же причине, что вы, вероятно, ожидали использовать (то есть атомарность).
Его сценарий использования совершенно другой и необычный, и это не то, что вы бросаете по прихоти, как с const,

1

Другие решения

«Плохое дизайнерское решение»? На самом деле, нет. Ключевое слово унаследовано от C, но сегодня оно очень мало используется. Это не активно осуждается, но его основное использование в простых случаях. Аппаратная часть памяти будет хорошим примером. Но не будет отображено в памяти std::deque<> так что в поддержке STL нет особого смысла.

0

По вопросам рекламы [email protected]