STL 中成员函数的 volatile-qualified 重载的不正确支持会阻止以通用方式使用容器,智能指针等。说,我想声明一个包装类,它提供了值语义并允许底层类型的不完整性:
#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 * ()
缺少适当的 volatile限定重载会导致错误:
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
成员函数限定符的通用代码中使用 STL (不涉及volatile
运算符)的对象。
STL 设计决策如此糟糕的原因是什么?为什么 STL 中没有正确支持volatile
成员函数限定符? volatile
成员函数限定符是否已被删除?
答案 0 :(得分:1)
It's a very good decision. It's because volatility would be outright wrong for most types.
Keep in mind that volatile
on an object means the object's fields can mutate spontaneously.
Consider the following, and assume the system guarantees that, at any given instant, begin
and end
will point to the same memory block:
template<class T>
class vector
{
T *begin;
T *end;
vector(vector const volatile &other) : begin(other.begin), end(other.end) { ... }
};
It turns out vector::vector(vector const volatile &)
is wrong, because it cannot ensure that begin
and end
are read simultaneously.
Consequently, the copy it creates might have a begin
and end
that are out of sync, even though the original was completely fine.
I think this should be enough to make you realize why volatile
is barely used.
It simply isn't used for the same reason that you were probably expecting used (i.e. atomics).
Its use case is entirely different and uncommon, and it is not something you throw around on a whim the way you might with const
.
答案 1 :(得分:0)
&#34;糟糕的设计决定&#34;?并不是的。关键字是从C继承的,但今天它几乎没用。它没有被主动弃用,但它的主要用途是简单的情况。内存映射硬件就是一个很好的例子。但是,它不会成为内存映射的std::deque<>
,因此STL支持这一点没有什么意义。