I am trying to create a volatile array and I need to access it using operator [].
I find no way to do that for std::array, however built-in arrays work fine.
With GCC 8.2.0 the following:
#include <iostream>
#include <array>
int main()
{
const volatile std::array<int,2> v = {1,2};
std::cout << v[0] << std::endl ;
}
gives
<source>: In function 'int main()':
<source>:6:21: error: passing 'const volatile std::array<int, 2>' as
'this' argument discards qualifiers [-fpermissive]
std::cout << v[0] << std::endl ;
^
In file included from <source>:2:
/opt/compiler-explorer/gcc-8.2.0/include/c++/8.2.0/array:185:7: note:
in call to 'constexpr std::array<_Tp, _Nm>::value_type& std::array<_Tp,
_Nm>::operator[](std::array<_Tp, _Nm>::size_type) [with _Tp = int; long
unsigned int _Nm = 2; std::array<_Tp, _Nm>::reference = int&;
std::array<_Tp, _Nm>::value_type = int; std::array<_Tp, _Nm>::size_type =
long unsigned int]'
operator[](size_type __n) noexcept
^~~~~~~~
Compiler returned: 1
while
#include <iostream>
int main()
{
const volatile int v[2] = {1,2};
std::cout << v[0] << std::endl ;
}
works perfectly fine.
How do I access a const volatile std::array?
You don't.
std::array
has two overloads of operator [](size_t)
. One for *this
is const, one if *this
is non-const. Neither of these will work for you - because *this
is const volatile.
If you use a const_cast
to remove the volatile qualifier the result will probably compile, and it might even appear to work. However the actual result is undefined behaviour (because the underlying object actually is volatile); that means it will stop working when you come to do the important demo to the customer.
For the language lawyers: n4296 is the last committee draft of the standard before C++14. Section 7.1.6.1 [dcl.type.cv] para 6 says:
If an attempt is made to refer to an object defined with a volatile-qualified type through the use of a glvalue with a non-volatile-qualified type, the program behavior is undefined".
I am pretty sure that similar language exists in all versions of the standard.
If you are using volatile
to support multi-threading - please don't. It doesn't actually help. You need to use std::atomic
or std::mutex
to do that. Volatile is useful to model special registers in a microprocessor address space.