Besides using it as intended, volatile is used in (template) metaprogramming. It can be used to prevent accidental overloading, as the volatile attribute (like const) takes part in overload resolution.
template <typename T>
class Foo {
std::enable_if_t<sizeof(T)==4, void> f(T& t)
{ std::cout << 1 << t; }
void f(T volatile& t)
{ std::cout << 2 << const_cast<T&>(t); }
void bar() { T t; f(t); }
};
This is legal; both overloads are potentially callable and do almost the same. The cast in the volatile
overload is legal as we know bar won't pass a non-volatile T
anyway. The volatile
version is strictly worse, though, so never chosen in overload resolution if the non-volatile f
is available.
Note that the code never actually depends on volatile
memory access.