What does the C++(11) standard say about conversions among volatile, const, volatile const, and "neither" types? I understand that it's well-defined and acceptable to assign a const type to a non-const and non-volatile type, but what about conversions among the following types (where T is some type)?
// T
T
T volatile
T const
T volatile const
// Pointer-to-T
T*
T volatile*
T const*
T volatile const*
// Volatile pointer-to-T
T* volatile
T volatile* volatile
T const* volatile
T volatile const* volatile
// Const pointer-to-T
T* const
T volatile* const
T const* const
T volatile const* const
// Volatile const pointer-to-T
T* volatile const
T volatile* volatile const
T const* volatile const
T volatile const* volatile const
As a simple example, consider the following code:
T volatile a;
T const b;
a = b; // implicit conversion from const to volatile; okay?
template<typename T>
void fcn(T& t)
{
t = b; // implicit conversion from const to non-const, which I assume is okay
}
fcn(a); // implicit conversion from volatile to non-volatile; okay?
What can you assign to what?
You can always assign volatile values to non-const values. You can also assign const and non-const values to volatile values. You can never assign anything to const values, because they're const.
Does a conversion occur?
No - it's just doing an assignment.
Why is this?
volatile
means that any accesses to an object cannot be optimized out. There are actually very few cases where volatile
is ever needed, or used. These cases are:
Because of this, it must be possible to assign volatile
to regular objects and vice versa. At the same time, however, volatile references shouldn't be implicitly converted to regular references, because that would potentially lead to reads and writes being optimized out.
What about const?
You can assign const stuff to anything, but nothing can be assigned to const (because it's const).