Search code examples
c++constantsvolatile

How do I access a const volatile std::array?


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?


Solution

  • 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.