[英]Proper support of volatile qualifier of member functions in STL
对STL中成员函数的volatile限定的重载的不正确支持会阻止以通用方式使用容器,智能指针等。 说,我想声明一个包装器类,该类提供值语义并允许基础类型不完整:
#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()
等。
它完全防止在使用volatile
成员函数限定符的通用代码中使用STL对象(不涉及const_cast
运算符)。
STL设计决策如此差的原因是什么? 为什么STL不正确支持volatile
成员函数限定符? 是否使用了volatile
成员函数限定符?
这是一个很好的决定。 这是因为对于大多数类型而言,波动率是完全错误的。
请记住,对象上的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
那样一时兴起的东西。
“糟糕的设计决策”? 并不是的。 关键字是从C继承的,但是今天很少使用。 它没有被弃用,但主要用途是在简单的情况下。 内存映射的硬件将是一个很好的例子。 但是不会有内存映射的std::deque<>
因此STL支持的意义不大。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.